@photivra/engine 1.4.0 → 2.0.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 +401 -6
- package/CITATION.cff +1 -1
- package/NODE_SUPPORT.md +64 -12
- package/README.md +301 -182
- package/SECURITY.md +37 -28
- package/THIRD_PARTY.md +148 -4
- package/dist/camera/equivalent-focal-length.d.ts +13 -14
- package/dist/camera/equivalent-focal-length.js +15 -13
- package/dist/camera/equivalent-focal-length.js.map +1 -1
- package/dist/camera/field-of-view.d.ts +30 -19
- package/dist/camera/field-of-view.js +67 -18
- package/dist/camera/field-of-view.js.map +1 -1
- package/dist/camera/lens-projection.d.ts +170 -0
- package/dist/camera/lens-projection.js +444 -0
- package/dist/camera/lens-projection.js.map +1 -0
- package/dist/camera/projected-object-size.d.ts +10 -11
- package/dist/camera/projected-object-size.js +12 -10
- package/dist/camera/projected-object-size.js.map +1 -1
- package/dist/capture/capture-export-metadata.d.ts +9 -10
- package/dist/capture/capture-export-metadata.js +8 -5
- package/dist/capture/capture-export-metadata.js.map +1 -1
- package/dist/capture/dng-import.d.ts +91 -0
- package/dist/capture/dng-import.js +343 -0
- package/dist/capture/dng-import.js.map +1 -0
- package/dist/capture/environment-raw-producer.d.ts +37 -17
- package/dist/capture/environment-raw-producer.js +43 -19
- package/dist/capture/environment-raw-producer.js.map +1 -1
- package/dist/capture/export-jpeg.d.ts +35 -4
- package/dist/capture/export-jpeg.js +133 -47
- package/dist/capture/export-jpeg.js.map +1 -1
- package/dist/capture/export-tiff.d.ts +48 -24
- package/dist/capture/export-tiff.js +91 -31
- package/dist/capture/export-tiff.js.map +1 -1
- package/dist/capture/focus-control.d.ts +42 -65
- package/dist/capture/focus-control.js +56 -75
- package/dist/capture/focus-control.js.map +1 -1
- package/dist/capture/host-yield-cadence.d.ts +25 -0
- package/dist/capture/host-yield-cadence.js +25 -0
- package/dist/capture/host-yield-cadence.js.map +1 -0
- package/dist/capture/linear-encoding.d.ts +14 -12
- package/dist/capture/linear-encoding.js +14 -13
- package/dist/capture/linear-encoding.js.map +1 -1
- package/dist/capture/lossless-jpeg.d.ts +27 -0
- package/dist/capture/lossless-jpeg.js +237 -0
- package/dist/capture/lossless-jpeg.js.map +1 -0
- package/dist/capture/native-environment-lean.d.ts +227 -0
- package/dist/capture/native-environment-lean.js +974 -0
- package/dist/capture/native-environment-lean.js.map +1 -0
- package/dist/capture/native-environment-optical-stage.d.ts +97 -0
- package/dist/capture/native-environment-optical-stage.js +340 -0
- package/dist/capture/native-environment-optical-stage.js.map +1 -0
- package/dist/capture/native-environment-raw.d.ts +140 -6
- package/dist/capture/native-environment-raw.js +435 -34
- package/dist/capture/native-environment-raw.js.map +1 -1
- package/dist/capture/native-raw-development.d.ts +118 -5
- package/dist/capture/native-raw-development.js +224 -59
- package/dist/capture/native-raw-development.js.map +1 -1
- package/dist/capture/native-raw-dng.d.ts +60 -0
- package/dist/capture/native-raw-dng.js +167 -0
- package/dist/capture/native-raw-dng.js.map +1 -0
- package/dist/capture/native-raw.d.ts +67 -10
- package/dist/capture/native-raw.js +90 -24
- package/dist/capture/native-raw.js.map +1 -1
- package/dist/capture/packed-sensor-raw.d.ts +160 -0
- package/dist/capture/packed-sensor-raw.js +221 -0
- package/dist/capture/packed-sensor-raw.js.map +1 -0
- package/dist/capture/photographic-export.d.ts +58 -35
- package/dist/capture/photographic-export.js +177 -70
- package/dist/capture/photographic-export.js.map +1 -1
- package/dist/capture/raw-development-kernel.d.ts +52 -0
- package/dist/capture/raw-development-kernel.js +88 -0
- package/dist/capture/raw-development-kernel.js.map +1 -0
- package/dist/capture/raw-frame-limits.d.ts +7 -7
- package/dist/capture/raw-frame-limits.js +7 -6
- package/dist/capture/raw-frame-limits.js.map +1 -1
- package/dist/capture/raw-frame-reconstruction.d.ts +8 -9
- package/dist/capture/raw-frame-reconstruction.js +9 -8
- package/dist/capture/raw-frame-reconstruction.js.map +1 -1
- package/dist/capture/raw-white-level.d.ts +55 -0
- package/dist/capture/raw-white-level.js +165 -0
- package/dist/capture/raw-white-level.js.map +1 -0
- package/dist/capture/release-sequence.d.ts +5 -7
- package/dist/capture/release-sequence.js +15 -13
- package/dist/capture/release-sequence.js.map +1 -1
- package/dist/capture/sensor-raw-frame.d.ts +5 -6
- package/dist/capture/sensor-raw-frame.js +26 -9
- package/dist/capture/sensor-raw-frame.js.map +1 -1
- package/dist/capture/sensor-raw-producer.d.ts +21 -13
- package/dist/capture/sensor-raw-producer.js +86 -25
- package/dist/capture/sensor-raw-producer.js.map +1 -1
- package/dist/capture/simulated-capture.d.ts +15 -16
- package/dist/capture/simulated-capture.js +22 -12
- package/dist/capture/simulated-capture.js.map +1 -1
- package/dist/color/camera-color-matrix.d.ts +69 -0
- package/dist/color/camera-color-matrix.js +132 -0
- package/dist/color/camera-color-matrix.js.map +1 -0
- package/dist/color/capture-color.d.ts +17 -10
- package/dist/color/capture-color.js +50 -17
- package/dist/color/capture-color.js.map +1 -1
- package/dist/color/chromatic-adaptation.d.ts +63 -0
- package/dist/color/chromatic-adaptation.js +91 -0
- package/dist/color/chromatic-adaptation.js.map +1 -0
- package/dist/color/color-difference.d.ts +104 -0
- package/dist/color/color-difference.js +205 -0
- package/dist/color/color-difference.js.map +1 -0
- package/dist/color/color-matching-functions.d.ts +168 -0
- package/dist/color/color-matching-functions.js +309 -0
- package/dist/color/color-matching-functions.js.map +1 -0
- package/dist/color/colorimetry-math.d.ts +52 -0
- package/dist/color/colorimetry-math.js +144 -0
- package/dist/color/colorimetry-math.js.map +1 -0
- package/dist/color/gamut-mapping.d.ts +54 -0
- package/dist/color/gamut-mapping.js +107 -0
- package/dist/color/gamut-mapping.js.map +1 -0
- package/dist/color/illuminants.d.ts +182 -0
- package/dist/color/illuminants.js +434 -0
- package/dist/color/illuminants.js.map +1 -0
- package/dist/color/rgb-color-spaces.d.ts +79 -0
- package/dist/color/rgb-color-spaces.js +115 -0
- package/dist/color/rgb-color-spaces.js.map +1 -0
- package/dist/color/sensor-color-development.d.ts +33 -11
- package/dist/color/sensor-color-development.js +104 -30
- package/dist/color/sensor-color-development.js.map +1 -1
- package/dist/color/srgb-icc.d.ts +9 -2
- package/dist/color/srgb-icc.js +16 -5
- package/dist/color/srgb-icc.js.map +1 -1
- package/dist/color/srgb-transfer.d.ts +1 -2
- package/dist/color/srgb-transfer.js +1 -1
- package/dist/color/srgb-transfer.js.map +1 -1
- package/dist/color/white-balance.d.ts +68 -19
- package/dist/color/white-balance.js +168 -35
- package/dist/color/white-balance.js.map +1 -1
- package/dist/composition/image-formation-plan.d.ts +152 -128
- package/dist/composition/image-formation-plan.js +292 -138
- package/dist/composition/image-formation-plan.js.map +1 -1
- package/dist/composition/plan-consumer.d.ts +6 -7
- package/dist/composition/plan-consumer.js +14 -11
- package/dist/composition/plan-consumer.js.map +1 -1
- package/dist/core/calculation-result.d.ts +21 -14
- package/dist/core/calculation-result.js +209 -11
- package/dist/core/calculation-result.js.map +1 -1
- package/dist/core/canonical-json.d.ts +13 -8
- package/dist/core/canonical-json.js +34 -15
- package/dist/core/canonical-json.js.map +1 -1
- package/dist/core/configuration-error.d.ts +5 -4
- package/dist/core/configuration-error.js +5 -3
- package/dist/core/configuration-error.js.map +1 -1
- package/dist/core/evidence-provenance.d.ts +12 -12
- package/dist/core/evidence-provenance.js +10 -9
- package/dist/core/evidence-provenance.js.map +1 -1
- package/dist/core/image-formation.d.ts +11 -10
- package/dist/core/image-formation.js +11 -9
- package/dist/core/image-formation.js.map +1 -1
- package/dist/core/owned-data.d.ts +9 -17
- package/dist/core/owned-data.js +9 -16
- package/dist/core/owned-data.js.map +1 -1
- package/dist/core/portable-math.d.ts +15 -0
- package/dist/core/portable-math.js +56 -0
- package/dist/core/portable-math.js.map +1 -0
- package/dist/core/record-validation.d.ts +48 -9
- package/dist/core/record-validation.js +93 -19
- package/dist/core/record-validation.js.map +1 -1
- package/dist/core/scientific-assurance.d.ts +16 -14
- package/dist/core/scientific-assurance.js +22 -18
- package/dist/core/scientific-assurance.js.map +1 -1
- package/dist/core/spectral-composition.d.ts +13 -14
- package/dist/core/spectral-composition.js +30 -27
- package/dist/core/spectral-composition.js.map +1 -1
- package/dist/core/spectral.d.ts +5 -6
- package/dist/core/spectral.js +9 -7
- package/dist/core/spectral.js.map +1 -1
- package/dist/core/validation.d.ts +3 -6
- package/dist/core/validation.js +3 -5
- package/dist/core/validation.js.map +1 -1
- package/dist/core/version.d.ts +6 -6
- package/dist/core/version.js +6 -5
- package/dist/core/version.js.map +1 -1
- package/dist/equipment/exposure-capabilities.d.ts +10 -10
- package/dist/equipment/exposure-capabilities.js +40 -30
- package/dist/equipment/exposure-capabilities.js.map +1 -1
- package/dist/equipment/generic-tier-assets.d.ts +13 -6
- package/dist/equipment/generic-tier-assets.js +34 -15
- package/dist/equipment/generic-tier-assets.js.map +1 -1
- package/dist/equipment/generic-tier-presets.d.ts +5 -6
- package/dist/equipment/generic-tier-presets.js +15 -13
- package/dist/equipment/generic-tier-presets.js.map +1 -1
- package/dist/equipment/iso-capabilities.d.ts +21 -22
- package/dist/equipment/iso-capabilities.js +49 -44
- package/dist/equipment/iso-capabilities.js.map +1 -1
- package/dist/equipment/metering-capabilities.d.ts +5 -6
- package/dist/equipment/metering-capabilities.js +22 -19
- package/dist/equipment/metering-capabilities.js.map +1 -1
- package/dist/equipment/release-capabilities.d.ts +3 -4
- package/dist/equipment/release-capabilities.js +18 -14
- package/dist/equipment/release-capabilities.js.map +1 -1
- package/dist/exposure/exposure-duration-control.d.ts +19 -17
- package/dist/exposure/exposure-duration-control.js +27 -23
- package/dist/exposure/exposure-duration-control.js.map +1 -1
- package/dist/exposure/exposure-mode-resolver.d.ts +42 -39
- package/dist/exposure/exposure-mode-resolver.js +127 -82
- package/dist/exposure/exposure-mode-resolver.js.map +1 -1
- package/dist/exposure/exposure.d.ts +17 -16
- package/dist/exposure/exposure.js +22 -15
- package/dist/exposure/exposure.js.map +1 -1
- package/dist/exposure/flash-ttl.d.ts +135 -0
- package/dist/exposure/flash-ttl.js +193 -0
- package/dist/exposure/flash-ttl.js.map +1 -0
- package/dist/exposure/flash.d.ts +144 -36
- package/dist/exposure/flash.js +259 -59
- package/dist/exposure/flash.js.map +1 -1
- package/dist/exposure/metering-scene-radiance.d.ts +10 -10
- package/dist/exposure/metering-scene-radiance.js +42 -23
- package/dist/exposure/metering-scene-radiance.js.map +1 -1
- package/dist/exposure/metering-target.d.ts +8 -8
- package/dist/exposure/metering-target.js +30 -20
- package/dist/exposure/metering-target.js.map +1 -1
- package/dist/exposure/metering-temporal.d.ts +16 -15
- package/dist/exposure/metering-temporal.js +41 -19
- package/dist/exposure/metering-temporal.js.map +1 -1
- package/dist/exposure/metering.d.ts +64 -17
- package/dist/exposure/metering.js +159 -30
- package/dist/exposure/metering.js.map +1 -1
- package/dist/exposure/program-line.d.ts +5 -5
- package/dist/exposure/program-line.js +20 -13
- package/dist/exposure/program-line.js.map +1 -1
- package/dist/facade/camera-preset.d.ts +8 -0
- package/dist/facade/camera-preset.js +102 -0
- package/dist/facade/camera-preset.js.map +1 -0
- package/dist/facade/chart-radiance-batch.d.ts +57 -0
- package/dist/facade/chart-radiance-batch.js +121 -0
- package/dist/facade/chart-radiance-batch.js.map +1 -0
- package/dist/facade/chart-scenes.d.ts +177 -0
- package/dist/facade/chart-scenes.js +232 -0
- package/dist/facade/chart-scenes.js.map +1 -0
- package/dist/facade/host-yield.d.ts +7 -0
- package/dist/facade/host-yield.js +23 -0
- package/dist/facade/host-yield.js.map +1 -0
- package/dist/facade/scene-radiance.d.ts +117 -0
- package/dist/facade/scene-radiance.js +205 -0
- package/dist/facade/scene-radiance.js.map +1 -0
- package/dist/facade/simulate-capture.d.ts +284 -0
- package/dist/facade/simulate-capture.js +1026 -0
- package/dist/facade/simulate-capture.js.map +1 -0
- package/dist/gpu/chart-radiance-gpu.d.ts +17 -0
- package/dist/gpu/chart-radiance-gpu.js +176 -0
- package/dist/gpu/chart-radiance-gpu.js.map +1 -0
- package/dist/gpu/image-kernel-accelerator.d.ts +132 -0
- package/dist/gpu/image-kernel-accelerator.js +720 -0
- package/dist/gpu/image-kernel-accelerator.js.map +1 -0
- package/dist/gpu/image-kernel-execution.d.ts +92 -0
- package/dist/gpu/image-kernel-execution.js +84 -0
- package/dist/gpu/image-kernel-execution.js.map +1 -0
- package/dist/gpu/sensor-stage-gpu.d.ts +44 -0
- package/dist/gpu/sensor-stage-gpu.js +317 -0
- package/dist/gpu/sensor-stage-gpu.js.map +1 -0
- package/dist/gpu/temporal-sum-gpu.d.ts +23 -0
- package/dist/gpu/temporal-sum-gpu.js +150 -0
- package/dist/gpu/temporal-sum-gpu.js.map +1 -0
- package/dist/gpu/webgpu-runtime.d.ts +63 -0
- package/dist/gpu/webgpu-runtime.js +215 -0
- package/dist/gpu/webgpu-runtime.js.map +1 -0
- package/dist/gpu/wgsl-chart-kernel.d.ts +30 -0
- package/dist/gpu/wgsl-chart-kernel.js +165 -0
- package/dist/gpu/wgsl-chart-kernel.js.map +1 -0
- package/dist/gpu/wgsl-kernels.d.ts +53 -0
- package/dist/gpu/wgsl-kernels.js +365 -0
- package/dist/gpu/wgsl-kernels.js.map +1 -0
- package/dist/gpu/wgsl-sensor-kernel.d.ts +64 -0
- package/dist/gpu/wgsl-sensor-kernel.js +409 -0
- package/dist/gpu/wgsl-sensor-kernel.js.map +1 -0
- package/dist/index.d.ts +89 -25
- package/dist/index.js +59 -15
- package/dist/index.js.map +1 -1
- package/dist/motion/camera-rotation.d.ts +92 -40
- package/dist/motion/camera-rotation.js +84 -47
- package/dist/motion/camera-rotation.js.map +1 -1
- package/dist/motion/capture-rotation-inverse-mapping.d.ts +37 -34
- package/dist/motion/capture-rotation-inverse-mapping.js +32 -24
- package/dist/motion/capture-rotation-inverse-mapping.js.map +1 -1
- package/dist/motion/capture-rotation-temporal-quadrature.d.ts +39 -35
- package/dist/motion/capture-rotation-temporal-quadrature.js +37 -28
- package/dist/motion/capture-rotation-temporal-quadrature.js.map +1 -1
- package/dist/motion/capture-rotation-trajectory.d.ts +32 -28
- package/dist/motion/capture-rotation-trajectory.js +36 -26
- package/dist/motion/capture-rotation-trajectory.js.map +1 -1
- package/dist/motion/capture-translation-parallax-temporal-quadrature.d.ts +23 -21
- package/dist/motion/capture-translation-parallax-temporal-quadrature.js +33 -14
- package/dist/motion/capture-translation-parallax-temporal-quadrature.js.map +1 -1
- package/dist/motion/extended-object-projection.d.ts +19 -16
- package/dist/motion/extended-object-projection.js +38 -18
- package/dist/motion/extended-object-projection.js.map +1 -1
- package/dist/motion/projected-motion.d.ts +18 -17
- package/dist/motion/projected-motion.js +25 -17
- package/dist/motion/projected-motion.js.map +1 -1
- package/dist/motion/temporal-exposure-sum.d.ts +55 -0
- package/dist/motion/temporal-exposure-sum.js +141 -0
- package/dist/motion/temporal-exposure-sum.js.map +1 -0
- package/dist/motion/video-sequence.d.ts +111 -0
- package/dist/motion/video-sequence.js +179 -0
- package/dist/motion/video-sequence.js.map +1 -0
- package/dist/optics/aperture.d.ts +14 -15
- package/dist/optics/aperture.js +13 -11
- package/dist/optics/aperture.js.map +1 -1
- package/dist/optics/atmospheric-haze.d.ts +83 -0
- package/dist/optics/atmospheric-haze.js +113 -0
- package/dist/optics/atmospheric-haze.js.map +1 -0
- package/dist/optics/brown-conrady-distortion.d.ts +116 -0
- package/dist/optics/brown-conrady-distortion.js +291 -0
- package/dist/optics/brown-conrady-distortion.js.map +1 -0
- package/dist/optics/circle-of-confusion.d.ts +10 -10
- package/dist/optics/circle-of-confusion.js +15 -11
- package/dist/optics/circle-of-confusion.js.map +1 -1
- package/dist/optics/complex-pupil-psf.d.ts +64 -33
- package/dist/optics/complex-pupil-psf.js +190 -98
- package/dist/optics/complex-pupil-psf.js.map +1 -1
- package/dist/optics/depth-of-field.d.ts +25 -15
- package/dist/optics/depth-of-field.js +67 -27
- package/dist/optics/depth-of-field.js.map +1 -1
- package/dist/optics/diffraction.d.ts +14 -13
- package/dist/optics/diffraction.js +14 -10
- package/dist/optics/diffraction.js.map +1 -1
- package/dist/optics/focus-breathing.d.ts +88 -27
- package/dist/optics/focus-breathing.js +114 -23
- package/dist/optics/focus-breathing.js.map +1 -1
- package/dist/optics/focus-state.d.ts +18 -18
- package/dist/optics/focus-state.js +21 -15
- package/dist/optics/focus-state.js.map +1 -1
- package/dist/optics/front-of-lens-filter.d.ts +45 -14
- package/dist/optics/front-of-lens-filter.js +259 -88
- package/dist/optics/front-of-lens-filter.js.map +1 -1
- package/dist/optics/illumination-vignetting.d.ts +16 -17
- package/dist/optics/illumination-vignetting.js +40 -17
- package/dist/optics/illumination-vignetting.js.map +1 -1
- package/dist/optics/irradiance-convolution.d.ts +59 -0
- package/dist/optics/irradiance-convolution.js +138 -0
- package/dist/optics/irradiance-convolution.js.map +1 -0
- package/dist/optics/lateral-chromatic-aberration.d.ts +33 -30
- package/dist/optics/lateral-chromatic-aberration.js +33 -23
- package/dist/optics/lateral-chromatic-aberration.js.map +1 -1
- package/dist/optics/lens-psf-kernels.d.ts +89 -0
- package/dist/optics/lens-psf-kernels.js +175 -0
- package/dist/optics/lens-psf-kernels.js.map +1 -0
- package/dist/optics/lens-psf-profile.d.ts +78 -46
- package/dist/optics/lens-psf-profile.js +335 -124
- package/dist/optics/lens-psf-profile.js.map +1 -1
- package/dist/optics/longitudinal-chromatic-aberration.d.ts +102 -0
- package/dist/optics/longitudinal-chromatic-aberration.js +210 -0
- package/dist/optics/longitudinal-chromatic-aberration.js.map +1 -0
- package/dist/optics/polygon-diffraction.d.ts +80 -23
- package/dist/optics/polygon-diffraction.js +130 -25
- package/dist/optics/polygon-diffraction.js.map +1 -1
- package/dist/optics/profile-contract.d.ts +5 -6
- package/dist/optics/profile-contract.js +14 -11
- package/dist/optics/profile-contract.js.map +1 -1
- package/dist/optics/psf-foundation.d.ts +23 -23
- package/dist/optics/psf-foundation.js +24 -21
- package/dist/optics/psf-foundation.js.map +1 -1
- package/dist/optics/pupil-vignetting.d.ts +118 -0
- package/dist/optics/pupil-vignetting.js +264 -0
- package/dist/optics/pupil-vignetting.js.map +1 -0
- package/dist/optics/radial-distortion.d.ts +34 -33
- package/dist/optics/radial-distortion.js +37 -30
- package/dist/optics/radial-distortion.js.map +1 -1
- package/dist/optics/scene-to-sensor-irradiance.d.ts +47 -33
- package/dist/optics/scene-to-sensor-irradiance.js +73 -45
- package/dist/optics/scene-to-sensor-irradiance.js.map +1 -1
- package/dist/optics/scene-to-sensor-quadrature.d.ts +23 -18
- package/dist/optics/scene-to-sensor-quadrature.js +16 -11
- package/dist/optics/scene-to-sensor-quadrature.js.map +1 -1
- package/dist/optics/sensor-aperture-rays.d.ts +20 -4
- package/dist/optics/sensor-aperture-rays.js +32 -14
- package/dist/optics/sensor-aperture-rays.js.map +1 -1
- package/dist/optics/sensor-environment-query.d.ts +81 -16
- package/dist/optics/sensor-environment-query.js +145 -12
- package/dist/optics/sensor-environment-query.js.map +1 -1
- package/dist/optics/sensor-psf-quadrature.d.ts +12 -10
- package/dist/optics/sensor-psf-quadrature.js +18 -11
- package/dist/optics/sensor-psf-quadrature.js.map +1 -1
- package/dist/optics/sensor-psf-support.d.ts +8 -6
- package/dist/optics/sensor-psf-support.js +8 -5
- package/dist/optics/sensor-psf-support.js.map +1 -1
- package/dist/optics/stray-light.d.ts +22 -19
- package/dist/optics/stray-light.js +18 -12
- package/dist/optics/stray-light.js.map +1 -1
- package/dist/optics/thin-lens.d.ts +10 -9
- package/dist/optics/thin-lens.js +12 -8
- package/dist/optics/thin-lens.js.map +1 -1
- package/dist/optics/zernike-wavefront.d.ts +154 -0
- package/dist/optics/zernike-wavefront.js +352 -0
- package/dist/optics/zernike-wavefront.js.map +1 -0
- package/dist/output/capture-corrected-sdr.d.ts +16 -8
- package/dist/output/capture-corrected-sdr.js +16 -8
- package/dist/output/capture-corrected-sdr.js.map +1 -1
- package/dist/output/capture-geometry.d.ts +34 -36
- package/dist/output/capture-geometry.js +52 -32
- package/dist/output/capture-geometry.js.map +1 -1
- package/dist/output/capture-sdr.d.ts +7 -6
- package/dist/output/capture-sdr.js +11 -8
- package/dist/output/capture-sdr.js.map +1 -1
- package/dist/output/crop.d.ts +22 -6
- package/dist/output/crop.js +40 -6
- package/dist/output/crop.js.map +1 -1
- package/dist/output/geometric-transforms.d.ts +60 -23
- package/dist/output/geometric-transforms.js +111 -24
- package/dist/output/geometric-transforms.js.map +1 -1
- package/dist/output/lens-corrections.d.ts +27 -19
- package/dist/output/lens-corrections.js +29 -13
- package/dist/output/lens-corrections.js.map +1 -1
- package/dist/output/native-capture-sdr.d.ts +71 -16
- package/dist/output/native-capture-sdr.js +190 -33
- package/dist/output/native-capture-sdr.js.map +1 -1
- package/dist/output/png-encoder.d.ts +65 -0
- package/dist/output/png-encoder.js +461 -0
- package/dist/output/png-encoder.js.map +1 -0
- package/dist/output/print-contrast-reference.d.ts +10 -9
- package/dist/output/print-contrast-reference.js +10 -8
- package/dist/output/print-contrast-reference.js.map +1 -1
- package/dist/output/print-detail.d.ts +18 -17
- package/dist/output/print-detail.js +12 -10
- package/dist/output/print-detail.js.map +1 -1
- package/dist/output/print-jpeg.d.ts +26 -5
- package/dist/output/print-jpeg.js +117 -50
- package/dist/output/print-jpeg.js.map +1 -1
- package/dist/output/print-plan.d.ts +19 -19
- package/dist/output/print-plan.js +11 -10
- package/dist/output/print-plan.js.map +1 -1
- package/dist/output/print-region-statistics.d.ts +14 -15
- package/dist/output/print-region-statistics.js +11 -11
- package/dist/output/print-region-statistics.js.map +1 -1
- package/dist/output/sdr-rendering.d.ts +48 -10
- package/dist/output/sdr-rendering.js +114 -25
- package/dist/output/sdr-rendering.js.map +1 -1
- package/dist/output/subject-framing-crop.d.ts +6 -10
- package/dist/output/subject-framing-crop.js +23 -13
- package/dist/output/subject-framing-crop.js.map +1 -1
- package/dist/processing/demosaic.d.ts +90 -0
- package/dist/processing/demosaic.js +275 -0
- package/dist/processing/demosaic.js.map +1 -0
- package/dist/processing/denoise.d.ts +68 -0
- package/dist/processing/denoise.js +214 -0
- package/dist/processing/denoise.js.map +1 -0
- package/dist/processing/focus-stacking.d.ts +17 -0
- package/dist/processing/focus-stacking.js +80 -0
- package/dist/processing/focus-stacking.js.map +1 -0
- package/dist/processing/hdr.d.ts +54 -0
- package/dist/processing/hdr.js +172 -0
- package/dist/processing/hdr.js.map +1 -0
- package/dist/processing/image-ops.d.ts +66 -0
- package/dist/processing/image-ops.js +192 -0
- package/dist/processing/image-ops.js.map +1 -0
- package/dist/processing/panorama.d.ts +51 -0
- package/dist/processing/panorama.js +305 -0
- package/dist/processing/panorama.js.map +1 -0
- package/dist/processing/processing-task.d.ts +85 -0
- package/dist/processing/processing-task.js +164 -0
- package/dist/processing/processing-task.js.map +1 -0
- package/dist/processing/tone-mapping.d.ts +69 -0
- package/dist/processing/tone-mapping.js +310 -0
- package/dist/processing/tone-mapping.js.map +1 -0
- package/dist/schema/camera.d.ts +5 -4
- package/dist/schema/illumination-spectral.d.ts +13 -19
- package/dist/schema/illumination-spectral.js +23 -19
- package/dist/schema/illumination-spectral.js.map +1 -1
- package/dist/schema/illumination-temporal.d.ts +12 -15
- package/dist/schema/illumination-temporal.js +43 -28
- package/dist/schema/illumination-temporal.js.map +1 -1
- package/dist/schema/illumination.d.ts +5 -4
- package/dist/schema/illumination.js +55 -20
- package/dist/schema/illumination.js.map +1 -1
- package/dist/schema/scene-radiance-temporal.d.ts +9 -11
- package/dist/schema/scene-radiance-temporal.js +26 -23
- package/dist/schema/scene-radiance-temporal.js.map +1 -1
- package/dist/schema/scene-radiance.d.ts +17 -17
- package/dist/schema/scene-radiance.js +56 -34
- package/dist/schema/scene-radiance.js.map +1 -1
- package/dist/schema/scene.d.ts +14 -13
- package/dist/schema/validation.d.ts +0 -1
- package/dist/schema/validation.js +17 -15
- package/dist/schema/validation.js.map +1 -1
- package/dist/sensor/accumulated-charge.d.ts +45 -64
- package/dist/sensor/accumulated-charge.js +41 -47
- package/dist/sensor/accumulated-charge.js.map +1 -1
- package/dist/sensor/architecture.d.ts +22 -25
- package/dist/sensor/architecture.js +17 -16
- package/dist/sensor/architecture.js.map +1 -1
- package/dist/sensor/camera-saturation-capacity.d.ts +21 -28
- package/dist/sensor/camera-saturation-capacity.js +36 -34
- package/dist/sensor/camera-saturation-capacity.js.map +1 -1
- package/dist/sensor/capture-color-sampling-binding.d.ts +46 -51
- package/dist/sensor/capture-color-sampling-binding.js +39 -41
- package/dist/sensor/capture-color-sampling-binding.js.map +1 -1
- package/dist/sensor/capture-mode-timing.d.ts +8 -9
- package/dist/sensor/capture-mode-timing.js +24 -21
- package/dist/sensor/capture-mode-timing.js.map +1 -1
- package/dist/sensor/capture-mode.d.ts +28 -30
- package/dist/sensor/capture-mode.js +33 -31
- package/dist/sensor/capture-mode.js.map +1 -1
- package/dist/sensor/color-sampling.d.ts +30 -33
- package/dist/sensor/color-sampling.js +32 -37
- package/dist/sensor/color-sampling.js.map +1 -1
- package/dist/sensor/constant-rate-temporal-integration.d.ts +19 -23
- package/dist/sensor/constant-rate-temporal-integration.js +28 -26
- package/dist/sensor/constant-rate-temporal-integration.js.map +1 -1
- package/dist/sensor/dark-current.d.ts +53 -49
- package/dist/sensor/dark-current.js +87 -46
- package/dist/sensor/dark-current.js.map +1 -1
- package/dist/sensor/environment-photo-signal.d.ts +71 -30
- package/dist/sensor/environment-photo-signal.js +127 -46
- package/dist/sensor/environment-photo-signal.js.map +1 -1
- package/dist/sensor/eqe-electron-rate.d.ts +14 -13
- package/dist/sensor/eqe-electron-rate.js +34 -14
- package/dist/sensor/eqe-electron-rate.js.map +1 -1
- package/dist/sensor/eqe-local-exposure.d.ts +24 -24
- package/dist/sensor/eqe-local-exposure.js +15 -11
- package/dist/sensor/eqe-local-exposure.js.map +1 -1
- package/dist/sensor/eqe-temporal-exposure.d.ts +11 -11
- package/dist/sensor/eqe-temporal-exposure.js +15 -10
- package/dist/sensor/eqe-temporal-exposure.js.map +1 -1
- package/dist/sensor/exposure-window.d.ts +48 -34
- package/dist/sensor/exposure-window.js +77 -36
- package/dist/sensor/exposure-window.js.map +1 -1
- package/dist/sensor/fixed-pattern-noise.d.ts +108 -0
- package/dist/sensor/fixed-pattern-noise.js +166 -0
- package/dist/sensor/fixed-pattern-noise.js.map +1 -0
- package/dist/sensor/iso-gain.d.ts +44 -0
- package/dist/sensor/iso-gain.js +119 -0
- package/dist/sensor/iso-gain.js.map +1 -0
- package/dist/sensor/iso-signal-chain.d.ts +25 -48
- package/dist/sensor/iso-signal-chain.js +52 -66
- package/dist/sensor/iso-signal-chain.js.map +1 -1
- package/dist/sensor/local-exposure-binding.d.ts +21 -21
- package/dist/sensor/local-exposure-binding.js +22 -18
- package/dist/sensor/local-exposure-binding.js.map +1 -1
- package/dist/sensor/optical-stack.d.ts +36 -40
- package/dist/sensor/optical-stack.js +34 -37
- package/dist/sensor/optical-stack.js.map +1 -1
- package/dist/sensor/photon-energy.d.ts +22 -28
- package/dist/sensor/photon-energy.js +42 -34
- package/dist/sensor/photon-energy.js.map +1 -1
- package/dist/sensor/physical-charge-capacity.d.ts +20 -30
- package/dist/sensor/physical-charge-capacity.js +35 -36
- package/dist/sensor/physical-charge-capacity.js.map +1 -1
- package/dist/sensor/pixel-pitch.d.ts +2 -3
- package/dist/sensor/pixel-pitch.js +4 -2
- package/dist/sensor/pixel-pitch.js.map +1 -1
- package/dist/sensor/radiometry-readiness.d.ts +13 -15
- package/dist/sensor/radiometry-readiness.js +20 -17
- package/dist/sensor/radiometry-readiness.js.map +1 -1
- package/dist/sensor/raw-readout.d.ts +173 -83
- package/dist/sensor/raw-readout.js +425 -160
- package/dist/sensor/raw-readout.js.map +1 -1
- package/dist/sensor/raw-reconstruction.d.ts +112 -44
- package/dist/sensor/raw-reconstruction.js +200 -47
- package/dist/sensor/raw-reconstruction.js.map +1 -1
- package/dist/sensor/readout-exposure-linkage.d.ts +103 -34
- package/dist/sensor/readout-exposure-linkage.js +125 -27
- package/dist/sensor/readout-exposure-linkage.js.map +1 -1
- package/dist/sensor/readout-timing.d.ts +43 -44
- package/dist/sensor/readout-timing.js +38 -30
- package/dist/sensor/readout-timing.js.map +1 -1
- package/dist/sensor/response-application-compatibility.d.ts +21 -28
- package/dist/sensor/response-application-compatibility.js +35 -34
- package/dist/sensor/response-application-compatibility.js.map +1 -1
- package/dist/sensor/response-operating-range.d.ts +26 -35
- package/dist/sensor/response-operating-range.js +40 -39
- package/dist/sensor/response-operating-range.js.map +1 -1
- package/dist/sensor/responsivity-photocurrent.d.ts +21 -29
- package/dist/sensor/responsivity-photocurrent.js +57 -40
- package/dist/sensor/responsivity-photocurrent.js.map +1 -1
- package/dist/sensor/sampling-aperture.d.ts +21 -25
- package/dist/sensor/sampling-aperture.js +29 -28
- package/dist/sensor/sampling-aperture.js.map +1 -1
- package/dist/sensor/scene-eqe-temporal-exposure.d.ts +14 -12
- package/dist/sensor/scene-eqe-temporal-exposure.js +13 -8
- package/dist/sensor/scene-eqe-temporal-exposure.js.map +1 -1
- package/dist/sensor/sensor-geometry.d.ts +28 -32
- package/dist/sensor/sensor-geometry.js +35 -20
- package/dist/sensor/sensor-geometry.js.map +1 -1
- package/dist/sensor/signal-noise.d.ts +14 -16
- package/dist/sensor/signal-noise.js +15 -13
- package/dist/sensor/signal-noise.js.map +1 -1
- package/dist/sensor/spatial-sample-reduction.d.ts +45 -60
- package/dist/sensor/spatial-sample-reduction.js +39 -48
- package/dist/sensor/spatial-sample-reduction.js.map +1 -1
- package/dist/sensor/spatial-sampling-quadrature.d.ts +46 -54
- package/dist/sensor/spatial-sampling-quadrature.js +31 -36
- package/dist/sensor/spatial-sampling-quadrature.js.map +1 -1
- package/dist/sensor/spatio-spectral-reduction.d.ts +32 -42
- package/dist/sensor/spatio-spectral-reduction.js +24 -29
- package/dist/sensor/spatio-spectral-reduction.js.map +1 -1
- package/dist/sensor/spectral-coverage.d.ts +6 -9
- package/dist/sensor/spectral-coverage.js +9 -6
- package/dist/sensor/spectral-coverage.js.map +1 -1
- package/dist/sensor/spectral-quadrature.d.ts +46 -60
- package/dist/sensor/spectral-quadrature.js +38 -48
- package/dist/sensor/spectral-quadrature.js.map +1 -1
- package/dist/sensor/spectral-response.d.ts +53 -41
- package/dist/sensor/spectral-response.js +80 -47
- package/dist/sensor/spectral-response.js.map +1 -1
- package/dist/sensor/stochastic-seed.d.ts +50 -0
- package/dist/sensor/stochastic-seed.js +123 -0
- package/dist/sensor/stochastic-seed.js.map +1 -0
- package/dist/sensor/temporal-eqe-sum.d.ts +2 -4
- package/dist/sensor/temporal-eqe-sum.js +5 -6
- package/dist/sensor/temporal-eqe-sum.js.map +1 -1
- package/dist/sensor/temporal-photo-signal.d.ts +5 -6
- package/dist/sensor/temporal-photo-signal.js +11 -10
- package/dist/sensor/temporal-photo-signal.js.map +1 -1
- package/dist/sensor/temporal-sample-binding.d.ts +1 -2
- package/dist/sensor/temporal-sample-binding.js +3 -3
- package/dist/sensor/temporal-sample-binding.js.map +1 -1
- package/dist/simulation/poc-simulation.d.ts +16 -16
- package/dist/simulation/poc-simulation.js +20 -15
- package/dist/simulation/poc-simulation.js.map +1 -1
- package/dist/stabilization/camera-shake.d.ts +42 -18
- package/dist/stabilization/camera-shake.js +43 -20
- package/dist/stabilization/camera-shake.js.map +1 -1
- package/dist/stabilization/system.d.ts +44 -41
- package/dist/stabilization/system.js +196 -108
- package/dist/stabilization/system.js.map +1 -1
- package/docs/AGENT_GUIDE.md +183 -0
- package/docs/API_REFERENCE.md +761 -2
- package/docs/QUICK_START.md +495 -0
- package/docs/USAGE.md +1719 -714
- package/docs/api/camera-equivalent-focal-length.md +6 -7
- package/docs/api/camera-field-of-view.md +16 -8
- package/docs/api/camera-lens-projection.md +246 -0
- package/docs/api/camera-projected-object-size.md +6 -5
- package/docs/api/capture-capture-export-metadata.md +10 -10
- package/docs/api/capture-dng-import.md +134 -0
- package/docs/api/capture-environment-raw-producer.md +17 -11
- package/docs/api/capture-export-jpeg.md +16 -0
- package/docs/api/capture-focus-control.md +25 -47
- package/docs/api/capture-linear-encoding.md +21 -12
- package/docs/api/capture-lossless-jpeg.md +49 -0
- package/docs/api/capture-native-environment-optical-stage.md +75 -0
- package/docs/api/capture-native-environment-raw.md +161 -4
- package/docs/api/capture-native-raw-development.md +69 -4
- package/docs/api/capture-native-raw-dng.md +84 -0
- package/docs/api/capture-native-raw.md +23 -8
- package/docs/api/capture-packed-sensor-raw.md +156 -0
- package/docs/api/capture-photographic-export.md +69 -31
- package/docs/api/capture-raw-frame-reconstruction.md +8 -8
- package/docs/api/capture-raw-white-level.md +37 -0
- package/docs/api/capture-release-sequence.md +6 -7
- package/docs/api/capture-sensor-raw-frame.md +6 -6
- package/docs/api/capture-sensor-raw-producer.md +17 -11
- package/docs/api/capture-simulated-capture.md +15 -15
- package/docs/api/color-camera-color-matrix.md +103 -0
- package/docs/api/color-capture-color.md +22 -11
- package/docs/api/color-chromatic-adaptation.md +82 -0
- package/docs/api/color-color-difference.md +134 -0
- package/docs/api/color-color-matching-functions.md +259 -0
- package/docs/api/color-colorimetry-math.md +54 -0
- package/docs/api/color-gamut-mapping.md +72 -0
- package/docs/api/color-illuminants.md +280 -0
- package/docs/api/color-rgb-color-spaces.md +151 -0
- package/docs/api/color-sensor-color-development.md +27 -0
- package/docs/api/color-srgb-icc.md +2 -4
- package/docs/api/color-white-balance.md +95 -19
- package/docs/api/composition-image-formation-plan.md +124 -95
- package/docs/api/composition-plan-consumer.md +7 -7
- package/docs/api/core-calculation-result.md +18 -14
- package/docs/api/core-configuration-error.md +1 -1
- package/docs/api/core-image-formation.md +7 -7
- package/docs/api/core-scientific-assurance.md +12 -10
- package/docs/api/core-spectral-composition.md +14 -14
- package/docs/api/core-spectral.md +6 -6
- package/docs/api/core-validation.md +3 -3
- package/docs/api/core-version.md +7 -6
- package/docs/api/equipment-exposure-capabilities.md +11 -10
- package/docs/api/equipment-generic-tier-assets.md +7 -2
- package/docs/api/equipment-generic-tier-presets.md +6 -6
- package/docs/api/equipment-iso-capabilities.md +18 -18
- package/docs/api/equipment-metering-capabilities.md +6 -6
- package/docs/api/equipment-release-capabilities.md +4 -4
- package/docs/api/exports.json +2213 -8
- package/docs/api/exposure-exposure-duration-control.md +9 -9
- package/docs/api/exposure-exposure-mode-resolver.md +35 -31
- package/docs/api/exposure-exposure.md +10 -10
- package/docs/api/exposure-flash-ttl.md +182 -0
- package/docs/api/exposure-flash.md +183 -28
- package/docs/api/exposure-metering-scene-radiance.md +11 -10
- package/docs/api/exposure-metering-target.md +9 -8
- package/docs/api/exposure-metering-temporal.md +8 -8
- package/docs/api/exposure-metering.md +69 -9
- package/docs/api/exposure-program-line.md +6 -5
- package/docs/api/facade-chart-radiance-batch.md +96 -0
- package/docs/api/facade-chart-scenes.md +240 -0
- package/docs/api/facade-scene-radiance.md +122 -0
- package/docs/api/facade-simulate-capture.md +324 -0
- package/docs/api/gpu-image-kernel-accelerator.md +157 -0
- package/docs/api/gpu-image-kernel-execution.md +152 -0
- package/docs/api/motion-camera-rotation.md +43 -26
- package/docs/api/motion-capture-rotation-inverse-mapping.md +24 -23
- package/docs/api/motion-capture-rotation-temporal-quadrature.md +22 -22
- package/docs/api/motion-capture-rotation-trajectory.md +15 -15
- package/docs/api/motion-capture-translation-parallax-temporal-quadrature.md +15 -14
- package/docs/api/motion-extended-object-projection.md +10 -8
- package/docs/api/motion-projected-motion.md +8 -8
- package/docs/api/motion-temporal-exposure-sum.md +98 -0
- package/docs/api/motion-video-sequence.md +159 -0
- package/docs/api/optics-aperture.md +8 -8
- package/docs/api/optics-atmospheric-haze.md +104 -0
- package/docs/api/optics-brown-conrady-distortion.md +123 -0
- package/docs/api/optics-circle-of-confusion.md +5 -4
- package/docs/api/optics-complex-pupil-psf.md +57 -16
- package/docs/api/optics-depth-of-field.md +12 -6
- package/docs/api/optics-diffraction.md +8 -7
- package/docs/api/optics-focus-breathing.md +104 -16
- package/docs/api/optics-focus-state.md +9 -10
- package/docs/api/optics-front-of-lens-filter.md +72 -14
- package/docs/api/optics-illumination-vignetting.md +10 -10
- package/docs/api/optics-irradiance-convolution.md +95 -0
- package/docs/api/optics-lateral-chromatic-aberration.md +22 -21
- package/docs/api/optics-lens-psf-kernels.md +72 -0
- package/docs/api/optics-lens-psf-profile.md +48 -26
- package/docs/api/optics-longitudinal-chromatic-aberration.md +128 -0
- package/docs/api/optics-polygon-diffraction.md +78 -13
- package/docs/api/optics-profile-contract.md +4 -4
- package/docs/api/optics-psf-foundation.md +12 -12
- package/docs/api/optics-pupil-vignetting.md +132 -0
- package/docs/api/optics-radial-distortion.md +12 -12
- package/docs/api/optics-scene-to-sensor-irradiance.md +25 -14
- package/docs/api/optics-scene-to-sensor-quadrature.md +15 -12
- package/docs/api/optics-sensor-aperture-rays.md +3 -2
- package/docs/api/optics-sensor-environment-query.md +52 -9
- package/docs/api/optics-sensor-psf-quadrature.md +13 -10
- package/docs/api/optics-stray-light.md +12 -11
- package/docs/api/optics-thin-lens.md +4 -3
- package/docs/api/optics-zernike-wavefront.md +229 -0
- package/docs/api/output-capture-corrected-sdr.md +10 -7
- package/docs/api/output-capture-geometry.md +35 -36
- package/docs/api/output-capture-sdr.md +4 -4
- package/docs/api/output-crop.md +7 -4
- package/docs/api/output-geometric-transforms.md +65 -19
- package/docs/api/output-lens-corrections.md +17 -15
- package/docs/api/output-native-capture-sdr.md +26 -13
- package/docs/api/output-png-encoder.md +105 -0
- package/docs/api/output-print-contrast-reference.md +8 -8
- package/docs/api/output-print-detail.md +14 -14
- package/docs/api/output-print-jpeg.md +22 -5
- package/docs/api/output-print-plan.md +18 -18
- package/docs/api/output-print-region-statistics.md +14 -14
- package/docs/api/output-sdr-rendering.md +52 -10
- package/docs/api/output-subject-framing-crop.md +5 -6
- package/docs/api/processing-demosaic.md +120 -0
- package/docs/api/processing-denoise.md +148 -0
- package/docs/api/processing-focus-stacking.md +41 -0
- package/docs/api/processing-hdr.md +113 -0
- package/docs/api/processing-panorama.md +82 -0
- package/docs/api/processing-processing-task.md +107 -0
- package/docs/api/processing-tone-mapping.md +142 -0
- package/docs/api/schema-camera.md +6 -4
- package/docs/api/schema-illumination-spectral.md +10 -11
- package/docs/api/schema-illumination-temporal.md +13 -15
- package/docs/api/schema-illumination.md +4 -4
- package/docs/api/schema-scene-radiance-temporal.md +10 -11
- package/docs/api/schema-scene-radiance.md +18 -17
- package/docs/api/schema-scene.md +9 -9
- package/docs/api/schema-validation.md +1 -1
- package/docs/api/sensor-accumulated-charge.md +12 -20
- package/docs/api/sensor-architecture.md +15 -16
- package/docs/api/sensor-camera-saturation-capacity.md +9 -11
- package/docs/api/sensor-capture-color-sampling-binding.md +47 -51
- package/docs/api/sensor-capture-mode-timing.md +9 -9
- package/docs/api/sensor-capture-mode.md +29 -30
- package/docs/api/sensor-color-sampling.md +31 -33
- package/docs/api/sensor-constant-rate-temporal-integration.md +10 -11
- package/docs/api/sensor-dark-current.md +30 -14
- package/docs/api/sensor-environment-photo-signal.md +13 -6
- package/docs/api/sensor-eqe-electron-rate.md +9 -8
- package/docs/api/sensor-eqe-local-exposure.md +18 -17
- package/docs/api/sensor-eqe-temporal-exposure.md +12 -11
- package/docs/api/sensor-exposure-window.md +24 -24
- package/docs/api/sensor-fixed-pattern-noise.md +104 -0
- package/docs/api/sensor-iso-gain.md +63 -0
- package/docs/api/sensor-iso-signal-chain.md +13 -22
- package/docs/api/sensor-local-exposure-binding.md +12 -13
- package/docs/api/sensor-optical-stack.md +37 -40
- package/docs/api/sensor-photon-energy.md +10 -11
- package/docs/api/sensor-physical-charge-capacity.md +8 -13
- package/docs/api/sensor-pixel-pitch.md +1 -1
- package/docs/api/sensor-radiometry-readiness.md +9 -9
- package/docs/api/sensor-raw-readout.md +118 -52
- package/docs/api/sensor-raw-reconstruction.md +97 -20
- package/docs/api/sensor-readout-exposure-linkage.md +120 -24
- package/docs/api/sensor-readout-timing.md +33 -35
- package/docs/api/sensor-response-application-compatibility.md +9 -11
- package/docs/api/sensor-response-operating-range.md +14 -18
- package/docs/api/sensor-responsivity-photocurrent.md +9 -12
- package/docs/api/sensor-sampling-aperture.md +22 -25
- package/docs/api/sensor-scene-eqe-temporal-exposure.md +9 -8
- package/docs/api/sensor-sensor-geometry.md +23 -24
- package/docs/api/sensor-signal-noise.md +10 -10
- package/docs/api/sensor-spatial-sample-reduction.md +27 -30
- package/docs/api/sensor-spatial-sampling-quadrature.md +37 -39
- package/docs/api/sensor-spatio-spectral-reduction.md +27 -29
- package/docs/api/sensor-spectral-coverage.md +5 -5
- package/docs/api/sensor-spectral-quadrature.md +33 -35
- package/docs/api/sensor-spectral-response.md +28 -16
- package/docs/api/sensor-temporal-photo-signal.md +6 -6
- package/docs/api/simulation-poc-simulation.md +17 -16
- package/docs/api/stabilization-camera-shake.md +29 -10
- package/docs/api/stabilization-system.md +25 -21
- package/docs/examples/production-request.json +3821 -2157
- package/docs/examples/simulate-capture.mjs +14 -0
- package/llms.txt +35 -0
- package/package.json +32 -12
- package/AGENTS.md +0 -674
- package/CONTRIBUTING.md +0 -76
- package/DCO +0 -33
- package/dist/camera/equivalent-focal-length.d.ts.map +0 -1
- package/dist/camera/field-of-view.d.ts.map +0 -1
- package/dist/camera/projected-object-size.d.ts.map +0 -1
- package/dist/capture/capture-export-metadata.d.ts.map +0 -1
- package/dist/capture/environment-raw-producer.d.ts.map +0 -1
- package/dist/capture/export-jpeg.d.ts.map +0 -1
- package/dist/capture/export-tiff.d.ts.map +0 -1
- package/dist/capture/focus-control.d.ts.map +0 -1
- package/dist/capture/linear-encoding.d.ts.map +0 -1
- package/dist/capture/native-environment-raw.d.ts.map +0 -1
- package/dist/capture/native-raw-development.d.ts.map +0 -1
- package/dist/capture/native-raw.d.ts.map +0 -1
- package/dist/capture/photographic-export.d.ts.map +0 -1
- package/dist/capture/raw-frame-limits.d.ts.map +0 -1
- package/dist/capture/raw-frame-reconstruction.d.ts.map +0 -1
- package/dist/capture/release-sequence.d.ts.map +0 -1
- package/dist/capture/sensor-raw-frame.d.ts.map +0 -1
- package/dist/capture/sensor-raw-producer.d.ts.map +0 -1
- package/dist/capture/simulated-capture.d.ts.map +0 -1
- package/dist/color/capture-color.d.ts.map +0 -1
- package/dist/color/sensor-color-development.d.ts.map +0 -1
- package/dist/color/srgb-icc.d.ts.map +0 -1
- package/dist/color/srgb-transfer.d.ts.map +0 -1
- package/dist/color/white-balance.d.ts.map +0 -1
- package/dist/composition/image-formation-plan.d.ts.map +0 -1
- package/dist/composition/plan-consumer.d.ts.map +0 -1
- package/dist/core/calculation-result.d.ts.map +0 -1
- package/dist/core/canonical-json.d.ts.map +0 -1
- package/dist/core/configuration-error.d.ts.map +0 -1
- package/dist/core/evidence-provenance.d.ts.map +0 -1
- package/dist/core/image-formation.d.ts.map +0 -1
- package/dist/core/owned-data.d.ts.map +0 -1
- package/dist/core/record-validation.d.ts.map +0 -1
- package/dist/core/scientific-assurance.d.ts.map +0 -1
- package/dist/core/spectral-composition.d.ts.map +0 -1
- package/dist/core/spectral.d.ts.map +0 -1
- package/dist/core/validation.d.ts.map +0 -1
- package/dist/core/version.d.ts.map +0 -1
- package/dist/equipment/exposure-capabilities.d.ts.map +0 -1
- package/dist/equipment/generic-tier-assets.d.ts.map +0 -1
- package/dist/equipment/generic-tier-presets.d.ts.map +0 -1
- package/dist/equipment/iso-capabilities.d.ts.map +0 -1
- package/dist/equipment/metering-capabilities.d.ts.map +0 -1
- package/dist/equipment/release-capabilities.d.ts.map +0 -1
- package/dist/exposure/exposure-duration-control.d.ts.map +0 -1
- package/dist/exposure/exposure-mode-resolver.d.ts.map +0 -1
- package/dist/exposure/exposure.d.ts.map +0 -1
- package/dist/exposure/flash.d.ts.map +0 -1
- package/dist/exposure/metering-scene-radiance.d.ts.map +0 -1
- package/dist/exposure/metering-target.d.ts.map +0 -1
- package/dist/exposure/metering-temporal.d.ts.map +0 -1
- package/dist/exposure/metering.d.ts.map +0 -1
- package/dist/exposure/program-line.d.ts.map +0 -1
- package/dist/index.d.ts.map +0 -1
- package/dist/motion/camera-rotation.d.ts.map +0 -1
- package/dist/motion/capture-rotation-inverse-mapping.d.ts.map +0 -1
- package/dist/motion/capture-rotation-temporal-quadrature.d.ts.map +0 -1
- package/dist/motion/capture-rotation-trajectory.d.ts.map +0 -1
- package/dist/motion/capture-translation-parallax-temporal-quadrature.d.ts.map +0 -1
- package/dist/motion/extended-object-projection.d.ts.map +0 -1
- package/dist/motion/projected-motion.d.ts.map +0 -1
- package/dist/optics/aperture.d.ts.map +0 -1
- package/dist/optics/circle-of-confusion.d.ts.map +0 -1
- package/dist/optics/complex-pupil-psf.d.ts.map +0 -1
- package/dist/optics/depth-of-field.d.ts.map +0 -1
- package/dist/optics/diffraction.d.ts.map +0 -1
- package/dist/optics/focus-breathing.d.ts.map +0 -1
- package/dist/optics/focus-state.d.ts.map +0 -1
- package/dist/optics/front-of-lens-filter.d.ts.map +0 -1
- package/dist/optics/illumination-vignetting.d.ts.map +0 -1
- package/dist/optics/lateral-chromatic-aberration.d.ts.map +0 -1
- package/dist/optics/lens-psf-profile.d.ts.map +0 -1
- package/dist/optics/polygon-diffraction.d.ts.map +0 -1
- package/dist/optics/profile-contract.d.ts.map +0 -1
- package/dist/optics/psf-foundation.d.ts.map +0 -1
- package/dist/optics/radial-distortion.d.ts.map +0 -1
- package/dist/optics/scene-to-sensor-irradiance.d.ts.map +0 -1
- package/dist/optics/scene-to-sensor-quadrature.d.ts.map +0 -1
- package/dist/optics/sensor-aperture-rays.d.ts.map +0 -1
- package/dist/optics/sensor-environment-query.d.ts.map +0 -1
- package/dist/optics/sensor-psf-quadrature.d.ts.map +0 -1
- package/dist/optics/sensor-psf-support.d.ts.map +0 -1
- package/dist/optics/stray-light.d.ts.map +0 -1
- package/dist/optics/thin-lens.d.ts.map +0 -1
- package/dist/output/capture-corrected-sdr.d.ts.map +0 -1
- package/dist/output/capture-geometry.d.ts.map +0 -1
- package/dist/output/capture-sdr.d.ts.map +0 -1
- package/dist/output/crop.d.ts.map +0 -1
- package/dist/output/geometric-transforms.d.ts.map +0 -1
- package/dist/output/lens-corrections.d.ts.map +0 -1
- package/dist/output/native-capture-sdr.d.ts.map +0 -1
- package/dist/output/print-contrast-reference.d.ts.map +0 -1
- package/dist/output/print-detail.d.ts.map +0 -1
- package/dist/output/print-jpeg.d.ts.map +0 -1
- package/dist/output/print-plan.d.ts.map +0 -1
- package/dist/output/print-region-statistics.d.ts.map +0 -1
- package/dist/output/sdr-rendering.d.ts.map +0 -1
- package/dist/output/subject-framing-crop.d.ts.map +0 -1
- package/dist/schema/camera.d.ts.map +0 -1
- package/dist/schema/camera.js +0 -3
- package/dist/schema/camera.js.map +0 -1
- package/dist/schema/illumination-spectral.d.ts.map +0 -1
- package/dist/schema/illumination-temporal.d.ts.map +0 -1
- package/dist/schema/illumination.d.ts.map +0 -1
- package/dist/schema/scene-radiance-temporal.d.ts.map +0 -1
- package/dist/schema/scene-radiance.d.ts.map +0 -1
- package/dist/schema/scene.d.ts.map +0 -1
- package/dist/schema/scene.js +0 -3
- package/dist/schema/scene.js.map +0 -1
- package/dist/schema/validation.d.ts.map +0 -1
- package/dist/sensor/accumulated-charge.d.ts.map +0 -1
- package/dist/sensor/architecture.d.ts.map +0 -1
- package/dist/sensor/camera-saturation-capacity.d.ts.map +0 -1
- package/dist/sensor/capture-color-sampling-binding.d.ts.map +0 -1
- package/dist/sensor/capture-mode-timing.d.ts.map +0 -1
- package/dist/sensor/capture-mode.d.ts.map +0 -1
- package/dist/sensor/color-sampling.d.ts.map +0 -1
- package/dist/sensor/constant-rate-temporal-integration.d.ts.map +0 -1
- package/dist/sensor/dark-current.d.ts.map +0 -1
- package/dist/sensor/environment-photo-signal.d.ts.map +0 -1
- package/dist/sensor/eqe-electron-rate.d.ts.map +0 -1
- package/dist/sensor/eqe-local-exposure.d.ts.map +0 -1
- package/dist/sensor/eqe-temporal-exposure.d.ts.map +0 -1
- package/dist/sensor/exposure-window.d.ts.map +0 -1
- package/dist/sensor/iso-signal-chain.d.ts.map +0 -1
- package/dist/sensor/local-exposure-binding.d.ts.map +0 -1
- package/dist/sensor/optical-stack.d.ts.map +0 -1
- package/dist/sensor/photon-energy.d.ts.map +0 -1
- package/dist/sensor/physical-charge-capacity.d.ts.map +0 -1
- package/dist/sensor/pixel-pitch.d.ts.map +0 -1
- package/dist/sensor/radiometry-readiness.d.ts.map +0 -1
- package/dist/sensor/raw-readout.d.ts.map +0 -1
- package/dist/sensor/raw-reconstruction.d.ts.map +0 -1
- package/dist/sensor/readout-exposure-linkage.d.ts.map +0 -1
- package/dist/sensor/readout-timing.d.ts.map +0 -1
- package/dist/sensor/response-application-compatibility.d.ts.map +0 -1
- package/dist/sensor/response-operating-range.d.ts.map +0 -1
- package/dist/sensor/responsivity-photocurrent.d.ts.map +0 -1
- package/dist/sensor/sampling-aperture.d.ts.map +0 -1
- package/dist/sensor/scene-eqe-temporal-exposure.d.ts.map +0 -1
- package/dist/sensor/sensor-geometry.d.ts.map +0 -1
- package/dist/sensor/signal-noise.d.ts.map +0 -1
- package/dist/sensor/spatial-sample-reduction.d.ts.map +0 -1
- package/dist/sensor/spatial-sampling-quadrature.d.ts.map +0 -1
- package/dist/sensor/spatio-spectral-reduction.d.ts.map +0 -1
- package/dist/sensor/spectral-coverage.d.ts.map +0 -1
- package/dist/sensor/spectral-quadrature.d.ts.map +0 -1
- package/dist/sensor/spectral-response.d.ts.map +0 -1
- package/dist/sensor/temporal-eqe-sum.d.ts.map +0 -1
- package/dist/sensor/temporal-photo-signal.d.ts.map +0 -1
- package/dist/sensor/temporal-sample-binding.d.ts.map +0 -1
- package/dist/simulation/poc-simulation.d.ts.map +0 -1
- package/dist/stabilization/camera-shake.d.ts.map +0 -1
- package/dist/stabilization/system.d.ts.map +0 -1
- package/docs/API_STYLE.md +0 -235
- package/docs/ARCHITECTURE.md +0 -356
- package/docs/AUTOMATION_COORDINATION.md +0 -190
- package/docs/CAPTURE_COLOR.md +0 -25
- package/docs/CAPTURE_CORRECTED_SDR.md +0 -25
- package/docs/CAPTURE_EXPORT_METADATA.md +0 -27
- package/docs/CAPTURE_SDR.md +0 -22
- package/docs/DEVELOPERS.md +0 -68
- package/docs/DIGITAL_OPTICS_FOUNDATION.md +0 -69
- package/docs/ENVIRONMENT_RAW_CAPTURE.md +0 -208
- package/docs/EXPORT_ACCEPTANCE.md +0 -133
- package/docs/GENERIC_TIER_PRESETS.md +0 -269
- package/docs/GEOMETRIC_PREPARATION_REUSE.md +0 -141
- package/docs/IMAGE_FORMATION.md +0 -247
- package/docs/LINEAR_CAPTURE_ENCODING.md +0 -25
- package/docs/MOTION_AND_SIGNAL.md +0 -250
- package/docs/NATIVE_CAPTURE_SDR.md +0 -70
- package/docs/NATIVE_CAPTURE_SDR_REVIEW.md +0 -37
- package/docs/NATIVE_CAPTURE_SDR_VALIDATION.md +0 -34
- package/docs/NATIVE_RAW_AND_PRINT.md +0 -47
- package/docs/NUMERICAL_CORRECTNESS.md +0 -191
- package/docs/PERFORMANCE_BASELINE.md +0 -56
- package/docs/PHOTOGRAPHIC_EXPORT.md +0 -206
- package/docs/PHYSICS_FOUNDATION.md +0 -426
- package/docs/POC_API.md +0 -278
- package/docs/POC_PROJECTION_PLATFORM_REFERENCE.md +0 -12
- package/docs/POC_PROJECTION_REUSE.md +0 -124
- package/docs/PRINT_195_196_REVIEW.md +0 -93
- package/docs/PRINT_196_ENGINE_ACCEPTANCE.md +0 -45
- package/docs/PRINT_CONTRAST_REFERENCE.md +0 -43
- package/docs/PRINT_DETAIL_ASSESSMENT.md +0 -81
- package/docs/PRINT_DETAIL_JPEG_EVIDENCE.md +0 -36
- package/docs/PRINT_DETAIL_SDR_EVIDENCE.md +0 -29
- package/docs/PRINT_DETAIL_VALIDATION.md +0 -36
- package/docs/PRINT_PLANNING.md +0 -75
- package/docs/PRINT_REGION_STATISTICS.md +0 -38
- package/docs/PROCESSED_OUTPUT.md +0 -157
- package/docs/PRODUCTION_COMPOSITION.md +0 -373
- package/docs/PRODUCTION_ENVIRONMENT_CAPTURE.md +0 -131
- package/docs/PROVENANCE.md +0 -115
- package/docs/PSF_FOUNDATION.md +0 -165
- package/docs/RAW_FRAME_ENVELOPE.md +0 -56
- package/docs/RAW_FRAME_RECONSTRUCTION.md +0 -30
- package/docs/RELEASE_1_0.md +0 -66
- package/docs/RELEASE_1_0_1.md +0 -61
- package/docs/RELEASE_1_1_0.md +0 -25
- package/docs/RELEASE_1_2_0.md +0 -51
- package/docs/RELEASE_1_3_0.md +0 -15
- package/docs/RELEASE_1_4_0.md +0 -23
- package/docs/RELEASE_AUDIT.md +0 -39
- package/docs/SCENE_RADIANCE_AND_ILLUMINATION.md +0 -298
- package/docs/SCENE_SENSOR_QUADRATURE.md +0 -98
- package/docs/SCENE_SENSOR_TEMPORAL_EXPOSURE.md +0 -86
- package/docs/SCIENTIFIC_ASSURANCE.md +0 -280
- package/docs/SCIENTIFIC_CONFORMANCE.md +0 -83
- package/docs/SDR_RENDERING.md +0 -33
- package/docs/SENSOR_APERTURE_RAYS.md +0 -23
- package/docs/SENSOR_ENVIRONMENT_QUERY.md +0 -86
- package/docs/SENSOR_EQE_LOCAL_EXPOSURE.md +0 -104
- package/docs/SENSOR_EQE_TEMPORAL_EXPOSURE.md +0 -74
- package/docs/SENSOR_PSF_QUADRATURE.md +0 -90
- package/docs/SENSOR_RAW_FRAME.md +0 -20
- package/docs/SENSOR_RAW_PRODUCER.md +0 -77
- package/docs/SIGNAL_CONFORMANCE.md +0 -23
- package/docs/SIMULATED_CAPTURE.md +0 -65
- package/docs/STABILIZATION.md +0 -234
- package/docs/TEMPORAL_PHOTO_RAW.md +0 -83
- package/docs/TIER_ACCEPTANCE.md +0 -129
- package/docs/TIER_PRESET_ACCEPTANCE.md +0 -59
- package/docs/V1_COMPOSITION_MAP.md +0 -123
- package/docs/V1_HELPER_REUSE_REVIEW.md +0 -60
- package/docs/V1_PERFORMANCE_DISPOSITION.md +0 -88
- package/docs/benchmarks/2026-10-01-main-baseline.json +0 -694
- package/docs/benchmarks/2026-10-02-geometric-preparation-reuse.json +0 -2190
- package/docs/benchmarks/2026-10-02-poc-projection-reuse.json +0 -2423
- package/docs/benchmarks/2026-10-02-v1-environment-gc-profile.json +0 -210
- package/docs/benchmarks/2026-10-02-v1-environment-ordinary.json +0 -187
- package/docs/benchmarks/2026-10-02-v1-geometry-gc-profile.json +0 -756
- package/docs/benchmarks/2026-10-02-v1-geometry-ordinary-1.json +0 -711
- package/docs/benchmarks/2026-10-02-v1-geometry-ordinary-2.json +0 -711
- package/docs/benchmarks/2026-10-02-v1-poc-gc-profile.json +0 -885
- package/docs/benchmarks/2026-10-02-v1-poc-ordinary-1.json +0 -868
- package/docs/benchmarks/2026-10-02-v1-poc-ordinary-2.json +0 -868
- package/docs/licenses/castleCSF-MIT.txt +0 -21
- package/docs/validation/documentation-fragments.json +0 -212
- package/docs/validation/native-capture-sdr-darwin-arm64-node26-review.jsonl +0 -4
- package/docs/validation/native-capture-sdr-darwin-arm64.jsonl +0 -3
- package/docs/validation/native-raw-print-2026-10-04/fractional-asymmetric-crop.jpg +0 -0
- package/docs/validation/native-raw-print-2026-10-04/gray-ramp.jpg +0 -0
- package/docs/validation/native-raw-print-2026-10-04/linear-area-checker.jpg +0 -0
- package/docs/validation/native-raw-print-2026-10-04/manifest.json +0 -218
- package/docs/validation/native-raw-print-2026-10-04/megapixel-native.jpg +0 -0
- package/docs/validation/native-raw-print-2026-10-04/native-color.jpg +0 -0
- package/docs/validation/native-raw-print-2026-10-04/photivra-native-full-megapixel-validation.json +0 -9
- package/docs/validation/native-raw-print-2026-10-04/photivra-native-full-megapixel.json +0 -29
- package/docs/validation/native-raw-print-2026-10-04/photivra-native-full-megapixel.json.codes.u16le.gz +0 -0
- package/docs/validation/native-raw-print-2026-10-04/photivra-native-full-megapixel.json.jpg +0 -0
- package/docs/validation/native-raw-print-2026-10-04/photivra-native-full-megapixel.json.rgb.gz +0 -0
- package/docs/validation/native-raw-print-2026-10-04/srgb.icc +0 -0
- package/docs/validation/native-raw-print-2026-10-04/validation.json +0 -41
- package/docs/validation/print-196-candidate-capabilities.json +0 -28
- package/docs/validation/print-196-candidate-evidence.json +0 -356
- package/docs/validation/print-196-engine-acceptance.json +0 -81
- package/docs/validation/print-detail-capabilities.json +0 -103
- package/docs/validation/print-detail-jpeg-evidence.json +0 -116
- package/docs/validation/print-detail-sdr-evidence.json +0 -81
- package/docs/validation/release-audit-inventory.json +0 -1306
- package/docs/validation/tier-acceptance-report-v1.json +0 -2538
|
@@ -0,0 +1,444 @@
|
|
|
1
|
+
// SPDX-License-Identifier: Apache-2.0
|
|
2
|
+
/**
|
|
3
|
+
* Ideal lens projection (mapping) functions. They convert between a scene direction and a point on the
|
|
4
|
+
* image plane.
|
|
5
|
+
*
|
|
6
|
+
* A radial projection maps the field angle theta (the angle from the optical axis) to the image
|
|
7
|
+
* radius r:
|
|
8
|
+
* rectilinear r = f tan(theta) (gnomonic / pinhole)
|
|
9
|
+
* equidistant r = f theta ("f-theta" fisheye)
|
|
10
|
+
* equisolid-angle r = 2 f sin(theta / 2) (equal-area fisheye)
|
|
11
|
+
* stereographic r = 2 f tan(theta / 2) (conformal fisheye)
|
|
12
|
+
* orthographic r = f sin(theta)
|
|
13
|
+
* The image point keeps the direction's azimuth about the optical axis, so every radial projection is
|
|
14
|
+
* rotationally symmetric. Equirectangular (spherical, or cylindrical equidistant) is not radial:
|
|
15
|
+
* x = f * longitude, y = f * latitude, where f is the image distance per radian.
|
|
16
|
+
*
|
|
17
|
+
* Sources: Kannala & Brandt 2006 (IEEE TPAMI 28:1335, generic camera model listing these
|
|
18
|
+
* projections, eqs. 1-5; free author copy); Miyamoto 1964 (JOSA 54:1060, fish-eye projection
|
|
19
|
+
* functions); Snyder 1987 (Map Projections - A Working Manual, USGS PP 1395, free) for the
|
|
20
|
+
* equirectangular and stereographic projections. Also see: Kingslake 1989 (A History of the
|
|
21
|
+
* Photographic Lens, ch. on fish-eye lenses); Ray 2002 (Applied Photographic Optics, 3rd ed., ch. 6
|
|
22
|
+
* and 47).
|
|
23
|
+
*
|
|
24
|
+
* These are ideal mapping functions. Real fisheye lenses deviate from them. Modelling a real lens
|
|
25
|
+
* would need a calibrated polynomial (for example Kannala-Brandt) with defensible provenance.
|
|
26
|
+
*
|
|
27
|
+
* Camera frame: +X right, +Y up, +Z along the optical axis toward the scene. Image-plane coordinates
|
|
28
|
+
* use the same non-inverted +X right / +Y up convention as the rest of the engine.
|
|
29
|
+
* @see docs/PHYSICS_FOUNDATION.md for the equations, units, coordinate conventions, known blockers
|
|
30
|
+
* and support limits.
|
|
31
|
+
*/
|
|
32
|
+
import { calculatedResult } from "../core/calculation-result.js";
|
|
33
|
+
import { InvalidScientificInputError, requirePositiveFinite } from "../core/validation.js";
|
|
34
|
+
import { rejectUnknownFields, requireInputKeys } from "../core/record-validation.js";
|
|
35
|
+
import { InvalidConfigurationError } from "../core/configuration-error.js";
|
|
36
|
+
export const LENS_PROJECTION_MODELS = Object.freeze([
|
|
37
|
+
"rectilinear",
|
|
38
|
+
"fisheye-equidistant",
|
|
39
|
+
"fisheye-equisolid-angle",
|
|
40
|
+
"fisheye-stereographic",
|
|
41
|
+
"fisheye-orthographic",
|
|
42
|
+
"equirectangular"
|
|
43
|
+
]);
|
|
44
|
+
const HALF_PI = Math.PI / 2;
|
|
45
|
+
/** Runtime parser for the projection discriminator. Rejects (fails closed on) unknown values. */
|
|
46
|
+
export function parseLensProjectionModel(value) {
|
|
47
|
+
if (typeof value !== "string" ||
|
|
48
|
+
!LENS_PROJECTION_MODELS.includes(value)) {
|
|
49
|
+
throw new InvalidConfigurationError("projectionModel must be one of " +
|
|
50
|
+
LENS_PROJECTION_MODELS.join(", ") +
|
|
51
|
+
".");
|
|
52
|
+
}
|
|
53
|
+
return value;
|
|
54
|
+
}
|
|
55
|
+
function requireRecord(name, value) {
|
|
56
|
+
if (typeof value !== "object" || value === null || Array.isArray(value)) {
|
|
57
|
+
throw new InvalidConfigurationError(`${name} must be an object.`);
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
function requireFinite(name, value) {
|
|
61
|
+
if (typeof value !== "number" || !Number.isFinite(value)) {
|
|
62
|
+
throw new InvalidScientificInputError(`${name} must be a finite number.`);
|
|
63
|
+
}
|
|
64
|
+
return value;
|
|
65
|
+
}
|
|
66
|
+
/**
|
|
67
|
+
* Largest field angle (radians) a radial model maps, and whether the model can reach it.
|
|
68
|
+
* Rectilinear, stereographic, equidistant and equisolid exclude the limit: the radius there is
|
|
69
|
+
* infinite, or the azimuth of the backward direction is undefined. Orthographic reaches 90 degrees.
|
|
70
|
+
*/
|
|
71
|
+
function radialFieldAngleLimit(model) {
|
|
72
|
+
switch (model) {
|
|
73
|
+
case "rectilinear":
|
|
74
|
+
return { radians: HALF_PI, inclusive: false };
|
|
75
|
+
case "fisheye-orthographic":
|
|
76
|
+
return { radians: HALF_PI, inclusive: true };
|
|
77
|
+
default:
|
|
78
|
+
return { radians: Math.PI, inclusive: false };
|
|
79
|
+
}
|
|
80
|
+
}
|
|
81
|
+
/** Image radius r(theta) for one radial model. */
|
|
82
|
+
export function radialProjectionImageRadius(model, focalLengthMm, fieldAngleRadians) {
|
|
83
|
+
switch (model) {
|
|
84
|
+
case "rectilinear":
|
|
85
|
+
return focalLengthMm * Math.tan(fieldAngleRadians);
|
|
86
|
+
case "fisheye-equidistant":
|
|
87
|
+
return focalLengthMm * fieldAngleRadians;
|
|
88
|
+
case "fisheye-equisolid-angle":
|
|
89
|
+
return 2 * focalLengthMm * Math.sin(fieldAngleRadians / 2);
|
|
90
|
+
case "fisheye-stereographic":
|
|
91
|
+
return 2 * focalLengthMm * Math.tan(fieldAngleRadians / 2);
|
|
92
|
+
case "fisheye-orthographic":
|
|
93
|
+
return focalLengthMm * Math.sin(fieldAngleRadians);
|
|
94
|
+
}
|
|
95
|
+
}
|
|
96
|
+
/**
|
|
97
|
+
* Largest image radius a radial model reaches inside its field-angle domain, in mm
|
|
98
|
+
* (Infinity for rectilinear and stereographic).
|
|
99
|
+
*/
|
|
100
|
+
function radialImageRadiusLimit(model, focalLengthMm) {
|
|
101
|
+
switch (model) {
|
|
102
|
+
case "rectilinear":
|
|
103
|
+
case "fisheye-stereographic":
|
|
104
|
+
return { radiusMm: Number.POSITIVE_INFINITY, inclusive: false };
|
|
105
|
+
case "fisheye-equidistant":
|
|
106
|
+
return { radiusMm: Math.PI * focalLengthMm, inclusive: false };
|
|
107
|
+
case "fisheye-equisolid-angle":
|
|
108
|
+
return { radiusMm: 2 * focalLengthMm, inclusive: false };
|
|
109
|
+
case "fisheye-orthographic":
|
|
110
|
+
return { radiusMm: focalLengthMm, inclusive: true };
|
|
111
|
+
}
|
|
112
|
+
}
|
|
113
|
+
/** Inverse theta(r) for one radial model; throws outside the image circle. */
|
|
114
|
+
export function radialProjectionFieldAngle(model, focalLengthMm, imageRadiusMm) {
|
|
115
|
+
const limit = radialImageRadiusLimit(model, focalLengthMm);
|
|
116
|
+
if (imageRadiusMm < 0 ||
|
|
117
|
+
imageRadiusMm > limit.radiusMm ||
|
|
118
|
+
(!limit.inclusive && imageRadiusMm === limit.radiusMm)) {
|
|
119
|
+
throw new InvalidScientificInputError(`Image radius lies outside the ${model} image circle.`);
|
|
120
|
+
}
|
|
121
|
+
switch (model) {
|
|
122
|
+
case "rectilinear":
|
|
123
|
+
return Math.atan(imageRadiusMm / focalLengthMm);
|
|
124
|
+
case "fisheye-equidistant":
|
|
125
|
+
return imageRadiusMm / focalLengthMm;
|
|
126
|
+
case "fisheye-equisolid-angle":
|
|
127
|
+
return 2 * Math.asin(imageRadiusMm / (2 * focalLengthMm));
|
|
128
|
+
case "fisheye-stereographic":
|
|
129
|
+
return 2 * Math.atan(imageRadiusMm / (2 * focalLengthMm));
|
|
130
|
+
case "fisheye-orthographic":
|
|
131
|
+
return Math.asin(Math.min(1, imageRadiusMm / focalLengthMm));
|
|
132
|
+
}
|
|
133
|
+
}
|
|
134
|
+
function assumptions(model) {
|
|
135
|
+
const common = [
|
|
136
|
+
"Ideal mapping function of a perfect projection; real lenses deviate from it and need calibrated distortion data",
|
|
137
|
+
"Camera frame +X right, +Y up, +Z toward the scene; image plane +X right, +Y up (non-inverted)"
|
|
138
|
+
];
|
|
139
|
+
if (model === "equirectangular") {
|
|
140
|
+
return [
|
|
141
|
+
"Equirectangular (spherical) projection: x = f * longitude, y = f * latitude, longitude measured about +Y from +Z",
|
|
142
|
+
...common
|
|
143
|
+
];
|
|
144
|
+
}
|
|
145
|
+
return [
|
|
146
|
+
`Radial projection ${model}; image azimuth equals scene azimuth about the optical axis`,
|
|
147
|
+
...common
|
|
148
|
+
];
|
|
149
|
+
}
|
|
150
|
+
function validateCommon(input, name) {
|
|
151
|
+
requireRecord(name, input);
|
|
152
|
+
const model = parseLensProjectionModel(input.projectionModel);
|
|
153
|
+
requirePositiveFinite("focalLengthMm", input.focalLengthMm);
|
|
154
|
+
return model;
|
|
155
|
+
}
|
|
156
|
+
/**
|
|
157
|
+
* Maps one camera-frame scene direction to its ideal image-plane point under the declared
|
|
158
|
+
* projection model.
|
|
159
|
+
*/
|
|
160
|
+
export function calculateLensProjectionImagePoint(input) {
|
|
161
|
+
requireInputKeys(input, "calculateLensProjectionImagePoint", ["projectionModel", "focalLengthMm", "direction"]);
|
|
162
|
+
const model = validateCommon(input, "input");
|
|
163
|
+
requireRecord("direction", input.direction);
|
|
164
|
+
rejectUnknownFields(input.direction, ["x", "y", "z"], "direction");
|
|
165
|
+
const x = requireFinite("direction.x", input.direction.x);
|
|
166
|
+
const y = requireFinite("direction.y", input.direction.y);
|
|
167
|
+
const z = requireFinite("direction.z", input.direction.z);
|
|
168
|
+
const length = Math.hypot(x, y, z);
|
|
169
|
+
if (!(length > 0) || !Number.isFinite(length)) {
|
|
170
|
+
throw new InvalidScientificInputError("direction must be a finite non-zero vector.");
|
|
171
|
+
}
|
|
172
|
+
const { imagePointMm, fieldAngleRadians } = lensProjectionImagePointValue(model, input.focalLengthMm, x, y, z);
|
|
173
|
+
return calculatedResult({
|
|
174
|
+
projectionModel: model,
|
|
175
|
+
imagePointMm,
|
|
176
|
+
fieldAngleRadians,
|
|
177
|
+
imageRadiusMm: Math.hypot(imagePointMm.x, imagePointMm.y)
|
|
178
|
+
}, `${model}-lens-projection`, "1.0.0", assumptions(model));
|
|
179
|
+
}
|
|
180
|
+
/**
|
|
181
|
+
* Inverse-maps one image-plane point to its unit camera-frame scene direction under the declared
|
|
182
|
+
* projection model. It rejects points outside the model's image circle. For equirectangular, it
|
|
183
|
+
* rejects points outside +/-pi longitude and +/-pi/2 latitude.
|
|
184
|
+
*/
|
|
185
|
+
export function calculateLensProjectionDirection(input) {
|
|
186
|
+
requireInputKeys(input, "calculateLensProjectionDirection", ["projectionModel", "focalLengthMm", "imagePointMm"]);
|
|
187
|
+
const model = validateCommon(input, "input");
|
|
188
|
+
requireRecord("imagePointMm", input.imagePointMm);
|
|
189
|
+
rejectUnknownFields(input.imagePointMm, ["x", "y"], "imagePointMm");
|
|
190
|
+
const px = requireFinite("imagePointMm.x", input.imagePointMm.x);
|
|
191
|
+
const py = requireFinite("imagePointMm.y", input.imagePointMm.y);
|
|
192
|
+
const imageRadiusMm = Math.hypot(px, py);
|
|
193
|
+
const direction = lensProjectionDirectionValue(model, input.focalLengthMm, px, py);
|
|
194
|
+
return calculatedResult({
|
|
195
|
+
projectionModel: model,
|
|
196
|
+
direction,
|
|
197
|
+
fieldAngleRadians: Math.atan2(Math.hypot(direction.x, direction.y), direction.z),
|
|
198
|
+
imageRadiusMm
|
|
199
|
+
}, `inverse-${model}-lens-projection`, "1.0.0", assumptions(model));
|
|
200
|
+
}
|
|
201
|
+
/** Signed angle subtended along one axis through the optical axis for a signed coordinate. */
|
|
202
|
+
function signedAxisAngle(model, focalLengthMm, coordinateMm) {
|
|
203
|
+
if (model === "equirectangular") {
|
|
204
|
+
// Along a horizontal or vertical line through the centre the angle is linear in position.
|
|
205
|
+
return coordinateMm / focalLengthMm;
|
|
206
|
+
}
|
|
207
|
+
const theta = radialProjectionFieldAngle(model, focalLengthMm, Math.abs(coordinateMm));
|
|
208
|
+
return coordinateMm < 0 ? -theta : theta;
|
|
209
|
+
}
|
|
210
|
+
/**
|
|
211
|
+
* Angular field of view across a centred sensor dimension along one axis through the optical
|
|
212
|
+
* axis: 2 * theta(d / 2) for radial models and d / f for equirectangular.
|
|
213
|
+
*
|
|
214
|
+
* For equirectangular, the result is the longitude span for a horizontal dimension and the latitude
|
|
215
|
+
* span for a vertical one. A sensor dimension larger than a fisheye's image circle is rejected, not
|
|
216
|
+
* clipped.
|
|
217
|
+
*/
|
|
218
|
+
export function calculateLensProjectionFieldOfView(input) {
|
|
219
|
+
requireInputKeys(input, "calculateLensProjectionFieldOfView", ["projectionModel", "focalLengthMm", "sensorDimensionMm"]);
|
|
220
|
+
const model = validateCommon(input, "input");
|
|
221
|
+
requirePositiveFinite("sensorDimensionMm", input.sensorDimensionMm);
|
|
222
|
+
const radians = 2 *
|
|
223
|
+
signedAxisAngle(model, input.focalLengthMm, input.sensorDimensionMm / 2);
|
|
224
|
+
if (model === "equirectangular" && radians > 2 * Math.PI) {
|
|
225
|
+
throw new InvalidScientificInputError("sensorDimensionMm exceeds the full 360-degree equirectangular span.");
|
|
226
|
+
}
|
|
227
|
+
return calculatedResult({
|
|
228
|
+
projectionModel: model,
|
|
229
|
+
radians,
|
|
230
|
+
degrees: (radians * 180) / Math.PI,
|
|
231
|
+
projectionDistanceMm: input.focalLengthMm
|
|
232
|
+
}, `${model}-field-of-view`, "1.0.0", [
|
|
233
|
+
...assumptions(model),
|
|
234
|
+
"Field of view is measured along one axis through the optical axis"
|
|
235
|
+
]);
|
|
236
|
+
}
|
|
237
|
+
/**
|
|
238
|
+
* Asymmetric angular span between two signed sensor coordinates on one axis through the optical
|
|
239
|
+
* axis, for off-centre crops.
|
|
240
|
+
*/
|
|
241
|
+
export function calculateLensProjectionFieldOfViewBounds(input) {
|
|
242
|
+
requireInputKeys(input, "calculateLensProjectionFieldOfViewBounds", ["projectionModel", "focalLengthMm", "minimumSensorCoordinateMm", "maximumSensorCoordinateMm"]);
|
|
243
|
+
const model = validateCommon(input, "input");
|
|
244
|
+
const minimum = requireFinite("minimumSensorCoordinateMm", input.minimumSensorCoordinateMm);
|
|
245
|
+
const maximum = requireFinite("maximumSensorCoordinateMm", input.maximumSensorCoordinateMm);
|
|
246
|
+
if (maximum <= minimum) {
|
|
247
|
+
throw new InvalidScientificInputError("maximumSensorCoordinateMm must be greater than minimumSensorCoordinateMm.");
|
|
248
|
+
}
|
|
249
|
+
const minimumRadians = signedAxisAngle(model, input.focalLengthMm, minimum);
|
|
250
|
+
const maximumRadians = signedAxisAngle(model, input.focalLengthMm, maximum);
|
|
251
|
+
const radians = maximumRadians - minimumRadians;
|
|
252
|
+
if (model === "equirectangular" && radians > 2 * Math.PI) {
|
|
253
|
+
throw new InvalidScientificInputError("Sensor bounds exceed the full 360-degree equirectangular span.");
|
|
254
|
+
}
|
|
255
|
+
return calculatedResult({
|
|
256
|
+
projectionModel: model,
|
|
257
|
+
minimumRadians,
|
|
258
|
+
maximumRadians,
|
|
259
|
+
radians,
|
|
260
|
+
minimumDegrees: (minimumRadians * 180) / Math.PI,
|
|
261
|
+
maximumDegrees: (maximumRadians * 180) / Math.PI,
|
|
262
|
+
degrees: (radians * 180) / Math.PI,
|
|
263
|
+
projectionDistanceMm: input.focalLengthMm
|
|
264
|
+
}, `asymmetric-${model}-field-of-view`, "1.0.0", [
|
|
265
|
+
...assumptions(model),
|
|
266
|
+
"Signed sensor-plane bounds are measured relative to the optical axis along one axis through it"
|
|
267
|
+
]);
|
|
268
|
+
}
|
|
269
|
+
/**
|
|
270
|
+
* @internal Image point of a non-zero camera-frame direction under one model (no envelope).
|
|
271
|
+
* Shared by the public mapping, geometric remaps and the environment ray query.
|
|
272
|
+
*/
|
|
273
|
+
export function lensProjectionImagePointValue(model, focalLengthMm, x, y, z) {
|
|
274
|
+
const length = Math.hypot(x, y, z);
|
|
275
|
+
const f = focalLengthMm;
|
|
276
|
+
const transverse = Math.hypot(x, y);
|
|
277
|
+
const fieldAngleRadians = Math.atan2(transverse, z);
|
|
278
|
+
let imagePointMm;
|
|
279
|
+
if (model === "equirectangular") {
|
|
280
|
+
const latitude = Math.asin(Math.max(-1, Math.min(1, y / length)));
|
|
281
|
+
const horizontal = Math.hypot(x, z);
|
|
282
|
+
if (horizontal === 0) {
|
|
283
|
+
// Poles have an undefined longitude; the projection is singular there.
|
|
284
|
+
throw new InvalidScientificInputError("Equirectangular projection is undefined at the poles (direction parallel to +/-Y).");
|
|
285
|
+
}
|
|
286
|
+
const longitude = Math.atan2(x, z);
|
|
287
|
+
imagePointMm = { x: f * longitude, y: f * latitude };
|
|
288
|
+
}
|
|
289
|
+
else {
|
|
290
|
+
const limit = radialFieldAngleLimit(model);
|
|
291
|
+
if (fieldAngleRadians > limit.radians ||
|
|
292
|
+
(!limit.inclusive && fieldAngleRadians === limit.radians)) {
|
|
293
|
+
throw new InvalidScientificInputError(`direction lies outside the ${model} projection domain.`);
|
|
294
|
+
}
|
|
295
|
+
const radius = radialProjectionImageRadius(model, f, fieldAngleRadians);
|
|
296
|
+
imagePointMm =
|
|
297
|
+
transverse === 0
|
|
298
|
+
? { x: 0, y: 0 }
|
|
299
|
+
: { x: (radius * x) / transverse, y: (radius * y) / transverse };
|
|
300
|
+
}
|
|
301
|
+
return { imagePointMm, fieldAngleRadians };
|
|
302
|
+
}
|
|
303
|
+
/** @internal Unit camera-frame direction of one image point under one model (no envelope). */
|
|
304
|
+
export function lensProjectionDirectionValue(model, focalLengthMm, px, py) {
|
|
305
|
+
const f = focalLengthMm;
|
|
306
|
+
const imageRadiusMm = Math.hypot(px, py);
|
|
307
|
+
let direction;
|
|
308
|
+
if (model === "equirectangular") {
|
|
309
|
+
const longitude = px / f;
|
|
310
|
+
const latitude = py / f;
|
|
311
|
+
if (Math.abs(longitude) > Math.PI || Math.abs(latitude) > HALF_PI) {
|
|
312
|
+
throw new InvalidScientificInputError("imagePointMm lies outside the equirectangular longitude/latitude domain.");
|
|
313
|
+
}
|
|
314
|
+
const cosLatitude = Math.cos(latitude);
|
|
315
|
+
direction = {
|
|
316
|
+
x: cosLatitude * Math.sin(longitude),
|
|
317
|
+
y: Math.sin(latitude),
|
|
318
|
+
z: cosLatitude * Math.cos(longitude)
|
|
319
|
+
};
|
|
320
|
+
}
|
|
321
|
+
else {
|
|
322
|
+
const theta = radialProjectionFieldAngle(model, f, imageRadiusMm);
|
|
323
|
+
const sinTheta = Math.sin(theta);
|
|
324
|
+
direction =
|
|
325
|
+
imageRadiusMm === 0
|
|
326
|
+
? { x: 0, y: 0, z: 1 }
|
|
327
|
+
: {
|
|
328
|
+
x: (sinTheta * px) / imageRadiusMm,
|
|
329
|
+
y: (sinTheta * py) / imageRadiusMm,
|
|
330
|
+
z: Math.cos(theta)
|
|
331
|
+
};
|
|
332
|
+
}
|
|
333
|
+
return direction;
|
|
334
|
+
}
|
|
335
|
+
/** d r / d theta of a radial model. */
|
|
336
|
+
function radialDerivative(model, f, theta) {
|
|
337
|
+
switch (model) {
|
|
338
|
+
case "rectilinear":
|
|
339
|
+
return f / Math.cos(theta) ** 2;
|
|
340
|
+
case "fisheye-equidistant":
|
|
341
|
+
return f;
|
|
342
|
+
case "fisheye-equisolid-angle":
|
|
343
|
+
return f * Math.cos(theta / 2);
|
|
344
|
+
case "fisheye-stereographic":
|
|
345
|
+
return f / Math.cos(theta / 2) ** 2;
|
|
346
|
+
case "fisheye-orthographic":
|
|
347
|
+
return f * Math.cos(theta);
|
|
348
|
+
}
|
|
349
|
+
}
|
|
350
|
+
/** Unit direction of an image point and its derivative d(direction)/d(point) (3 x 2). */
|
|
351
|
+
function directionWithDerivative(model, f, px, py) {
|
|
352
|
+
const direction = lensProjectionDirectionValue(model, f, px, py);
|
|
353
|
+
if (model === "equirectangular") {
|
|
354
|
+
const lambda = px / f;
|
|
355
|
+
const phi = py / f;
|
|
356
|
+
const cp = Math.cos(phi);
|
|
357
|
+
const sp = Math.sin(phi);
|
|
358
|
+
const cl = Math.cos(lambda);
|
|
359
|
+
const sl = Math.sin(lambda);
|
|
360
|
+
return {
|
|
361
|
+
direction,
|
|
362
|
+
derivative: [
|
|
363
|
+
[(cp * cl) / f, (-sp * sl) / f],
|
|
364
|
+
[0, cp / f],
|
|
365
|
+
[(-cp * sl) / f, (-sp * cl) / f]
|
|
366
|
+
]
|
|
367
|
+
};
|
|
368
|
+
}
|
|
369
|
+
const rho = Math.hypot(px, py);
|
|
370
|
+
if (rho === 0) {
|
|
371
|
+
const a = 1 / radialDerivative(model, f, 0);
|
|
372
|
+
return { direction, derivative: [[a, 0], [0, a], [0, 0]] };
|
|
373
|
+
}
|
|
374
|
+
const theta = radialProjectionFieldAngle(model, f, rho);
|
|
375
|
+
const dTheta = 1 / radialDerivative(model, f, theta);
|
|
376
|
+
const a = Math.sin(theta) / rho;
|
|
377
|
+
const aPrime = (Math.cos(theta) * dTheta * rho - Math.sin(theta)) / (rho * rho);
|
|
378
|
+
const ux = px / rho;
|
|
379
|
+
const uy = py / rho;
|
|
380
|
+
const dz = -Math.sin(theta) * dTheta;
|
|
381
|
+
return {
|
|
382
|
+
direction,
|
|
383
|
+
derivative: [
|
|
384
|
+
[a + aPrime * px * ux, aPrime * px * uy],
|
|
385
|
+
[aPrime * py * ux, a + aPrime * py * uy],
|
|
386
|
+
[dz * ux, dz * uy]
|
|
387
|
+
]
|
|
388
|
+
};
|
|
389
|
+
}
|
|
390
|
+
/** Image point of a unit direction and its derivative d(point)/d(direction) (2 x 3). */
|
|
391
|
+
function imagePointWithDerivative(model, f, v) {
|
|
392
|
+
const point = lensProjectionImagePointValue(model, f, v.x, v.y, v.z).imagePointMm;
|
|
393
|
+
if (model === "equirectangular") {
|
|
394
|
+
const h2 = v.x * v.x + v.z * v.z;
|
|
395
|
+
const c = Math.sqrt(Math.max(0, 1 - v.y * v.y));
|
|
396
|
+
return {
|
|
397
|
+
point,
|
|
398
|
+
derivative: [
|
|
399
|
+
[(f * v.z) / h2, 0, (-f * v.x) / h2],
|
|
400
|
+
[0, f / c, 0]
|
|
401
|
+
]
|
|
402
|
+
};
|
|
403
|
+
}
|
|
404
|
+
const t = Math.hypot(v.x, v.y);
|
|
405
|
+
const theta = Math.atan2(t, v.z);
|
|
406
|
+
if (theta < 1e-9) {
|
|
407
|
+
const g = radialDerivative(model, f, 0);
|
|
408
|
+
return { point, derivative: [[g, 0, 0], [0, g, 0]] };
|
|
409
|
+
}
|
|
410
|
+
const s = Math.sin(theta);
|
|
411
|
+
const g = radialProjectionImageRadius(model, f, theta);
|
|
412
|
+
const b = g / s;
|
|
413
|
+
const bPrime = (radialDerivative(model, f, theta) * s - g * Math.cos(theta)) / (s * s);
|
|
414
|
+
// q = b(theta) (vx, vy); on the unit sphere d theta = -d vz / sin theta.
|
|
415
|
+
const k = -bPrime / s;
|
|
416
|
+
return {
|
|
417
|
+
point,
|
|
418
|
+
derivative: [
|
|
419
|
+
[b, 0, k * v.x],
|
|
420
|
+
[0, b, k * v.y]
|
|
421
|
+
]
|
|
422
|
+
};
|
|
423
|
+
}
|
|
424
|
+
/**
|
|
425
|
+
* @internal Destination-to-source remap between two ideal projections: the destination point is
|
|
426
|
+
* unprojected with the destination model and reprojected with the source model. Returns the
|
|
427
|
+
* source point and the 2 x 2 Jacobian d(source)/d(destination), row-major.
|
|
428
|
+
*/
|
|
429
|
+
export function lensProjectionRemapValue(destinationModel, destinationFocalLengthMm, sourceModel, sourceFocalLengthMm, px, py) {
|
|
430
|
+
const inverse = directionWithDerivative(destinationModel, destinationFocalLengthMm, px, py);
|
|
431
|
+
const forward = imagePointWithDerivative(sourceModel, sourceFocalLengthMm, inverse.direction);
|
|
432
|
+
const d = inverse.derivative;
|
|
433
|
+
const q = forward.derivative;
|
|
434
|
+
const j = (row, column) => q[row][0] * d[0][column] + q[row][1] * d[1][column] + q[row][2] * d[2][column];
|
|
435
|
+
return {
|
|
436
|
+
sourcePointMm: forward.point,
|
|
437
|
+
jacobian: [j(0, 0), j(0, 1), j(1, 0), j(1, 1)]
|
|
438
|
+
};
|
|
439
|
+
}
|
|
440
|
+
/** @internal Signed angle along one axis through the optical axis (exported for sampling plans). */
|
|
441
|
+
export function lensProjectionSignedAxisAngle(model, focalLengthMm, coordinateMm) {
|
|
442
|
+
return signedAxisAngle(model, focalLengthMm, coordinateMm);
|
|
443
|
+
}
|
|
444
|
+
//# sourceMappingURL=lens-projection.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"lens-projection.js","sourceRoot":"","sources":["../../src/camera/lens-projection.ts"],"names":[],"mappings":"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","sourcesContent":["// SPDX-License-Identifier: Apache-2.0\n\n/**\n * Ideal lens projection (mapping) functions. They convert between a scene direction and a point on the\n * image plane.\n *\n * A radial projection maps the field angle theta (the angle from the optical axis) to the image\n * radius r:\n * rectilinear r = f tan(theta) (gnomonic / pinhole)\n * equidistant r = f theta (\"f-theta\" fisheye)\n * equisolid-angle r = 2 f sin(theta / 2) (equal-area fisheye)\n * stereographic r = 2 f tan(theta / 2) (conformal fisheye)\n * orthographic r = f sin(theta)\n * The image point keeps the direction's azimuth about the optical axis, so every radial projection is\n * rotationally symmetric. Equirectangular (spherical, or cylindrical equidistant) is not radial:\n * x = f * longitude, y = f * latitude, where f is the image distance per radian.\n *\n * Sources: Kannala & Brandt 2006 (IEEE TPAMI 28:1335, generic camera model listing these\n * projections, eqs. 1-5; free author copy); Miyamoto 1964 (JOSA 54:1060, fish-eye projection\n * functions); Snyder 1987 (Map Projections - A Working Manual, USGS PP 1395, free) for the\n * equirectangular and stereographic projections. Also see: Kingslake 1989 (A History of the\n * Photographic Lens, ch. on fish-eye lenses); Ray 2002 (Applied Photographic Optics, 3rd ed., ch. 6\n * and 47).\n *\n * These are ideal mapping functions. Real fisheye lenses deviate from them. Modelling a real lens\n * would need a calibrated polynomial (for example Kannala-Brandt) with defensible provenance.\n *\n * Camera frame: +X right, +Y up, +Z along the optical axis toward the scene. Image-plane coordinates\n * use the same non-inverted +X right / +Y up convention as the rest of the engine.\n * @see docs/PHYSICS_FOUNDATION.md for the equations, units, coordinate conventions, known blockers\n * and support limits.\n */\n\nimport {\n calculatedResult,\n type CalculationResult\n} from \"../core/calculation-result.js\";\nimport {\n InvalidScientificInputError,\n requirePositiveFinite\n} from \"../core/validation.js\";\nimport { rejectUnknownFields, requireInputKeys } from \"../core/record-validation.js\";\nimport { InvalidConfigurationError } from \"../core/configuration-error.js\";\n\n/** Ideal projection model discriminator. `rectilinear` is the engine default. */\nexport type LensProjectionModel =\n | \"rectilinear\"\n | \"fisheye-equidistant\"\n | \"fisheye-equisolid-angle\"\n | \"fisheye-stereographic\"\n | \"fisheye-orthographic\"\n | \"equirectangular\";\n\n/** Radial (rotationally symmetric) projection models. */\nexport type RadialLensProjectionModel = Exclude<\n LensProjectionModel,\n \"equirectangular\"\n>;\n\nexport const LENS_PROJECTION_MODELS: readonly LensProjectionModel[] =\n Object.freeze([\n \"rectilinear\",\n \"fisheye-equidistant\",\n \"fisheye-equisolid-angle\",\n \"fisheye-stereographic\",\n \"fisheye-orthographic\",\n \"equirectangular\"\n ]);\n\nexport interface LensDirection {\n /** Camera-frame direction component, +X right. Any positive length. */\n x: number;\n /** Camera-frame direction component, +Y up. */\n y: number;\n /** Camera-frame direction component along the optical axis toward the scene. */\n z: number;\n}\n\nexport interface CalculateLensProjectionImagePointInput {\n projectionModel: LensProjectionModel;\n /**\n * Projection scale in millimetres: the focal length f of the mapping function, or for\n * equirectangular the image distance per radian.\n */\n focalLengthMm: number;\n /** Scene direction in the camera frame. Need not be normalized; must be non-zero. */\n direction: LensDirection;\n}\n\nexport interface LensProjectionImagePoint {\n projectionModel: LensProjectionModel;\n imagePointMm: { x: number; y: number };\n /** Angle between the direction and the optical axis, in radians. */\n fieldAngleRadians: number;\n /** Distance of the image point from the optical axis, in millimetres. */\n imageRadiusMm: number;\n}\n\nexport interface CalculateLensProjectionDirectionInput {\n projectionModel: LensProjectionModel;\n focalLengthMm: number;\n /** Image-plane point relative to the optical axis, in millimetres. */\n imagePointMm: { x: number; y: number };\n}\n\nexport interface LensProjectionDirection {\n projectionModel: LensProjectionModel;\n /** Unit direction in the camera frame. */\n direction: LensDirection;\n fieldAngleRadians: number;\n imageRadiusMm: number;\n}\n\nexport interface CalculateLensProjectionFieldOfViewInput {\n projectionModel: LensProjectionModel;\n focalLengthMm: number;\n /** Centred sensor/capture dimension along one axis through the optical axis, in mm. */\n sensorDimensionMm: number;\n}\n\nexport interface CalculateLensProjectionFieldOfViewBoundsInput {\n projectionModel: LensProjectionModel;\n focalLengthMm: number;\n /** Signed minimum sensor coordinate along one axis through the optical axis, in mm. */\n minimumSensorCoordinateMm: number;\n /** Signed maximum sensor coordinate along the same axis, in mm. */\n maximumSensorCoordinateMm: number;\n}\n\nexport interface LensProjectionFieldOfView {\n projectionModel: LensProjectionModel;\n degrees: number;\n radians: number;\n /** Projection scale used by the mapping, in millimetres. */\n projectionDistanceMm: number;\n}\n\nexport interface LensProjectionFieldOfViewBounds {\n projectionModel: LensProjectionModel;\n minimumRadians: number;\n maximumRadians: number;\n radians: number;\n minimumDegrees: number;\n maximumDegrees: number;\n degrees: number;\n projectionDistanceMm: number;\n}\n\nconst HALF_PI = Math.PI / 2;\n\n/** Runtime parser for the projection discriminator. Rejects (fails closed on) unknown values. */\nexport function parseLensProjectionModel(\n value: unknown\n): LensProjectionModel {\n if (\n typeof value !== \"string\" ||\n !(LENS_PROJECTION_MODELS as readonly string[]).includes(value)\n ) {\n throw new InvalidConfigurationError(\n \"projectionModel must be one of \" +\n LENS_PROJECTION_MODELS.join(\", \") +\n \".\"\n );\n }\n return value as LensProjectionModel;\n}\n\nfunction requireRecord(name: string, value: unknown): void {\n if (typeof value !== \"object\" || value === null || Array.isArray(value)) {\n throw new InvalidConfigurationError(`${name} must be an object.`);\n }\n}\n\nfunction requireFinite(name: string, value: unknown): number {\n if (typeof value !== \"number\" || !Number.isFinite(value)) {\n throw new InvalidScientificInputError(`${name} must be a finite number.`);\n }\n return value;\n}\n\n/**\n * Largest field angle (radians) a radial model maps, and whether the model can reach it.\n * Rectilinear, stereographic, equidistant and equisolid exclude the limit: the radius there is\n * infinite, or the azimuth of the backward direction is undefined. Orthographic reaches 90 degrees.\n */\nfunction radialFieldAngleLimit(model: RadialLensProjectionModel): {\n radians: number;\n inclusive: boolean;\n} {\n switch (model) {\n case \"rectilinear\":\n return { radians: HALF_PI, inclusive: false };\n case \"fisheye-orthographic\":\n return { radians: HALF_PI, inclusive: true };\n default:\n return { radians: Math.PI, inclusive: false };\n }\n}\n\n/** Image radius r(theta) for one radial model. */\nexport function radialProjectionImageRadius(\n model: RadialLensProjectionModel,\n focalLengthMm: number,\n fieldAngleRadians: number\n): number {\n switch (model) {\n case \"rectilinear\":\n return focalLengthMm * Math.tan(fieldAngleRadians);\n case \"fisheye-equidistant\":\n return focalLengthMm * fieldAngleRadians;\n case \"fisheye-equisolid-angle\":\n return 2 * focalLengthMm * Math.sin(fieldAngleRadians / 2);\n case \"fisheye-stereographic\":\n return 2 * focalLengthMm * Math.tan(fieldAngleRadians / 2);\n case \"fisheye-orthographic\":\n return focalLengthMm * Math.sin(fieldAngleRadians);\n }\n}\n\n/**\n * Largest image radius a radial model reaches inside its field-angle domain, in mm\n * (Infinity for rectilinear and stereographic).\n */\nfunction radialImageRadiusLimit(\n model: RadialLensProjectionModel,\n focalLengthMm: number\n): { radiusMm: number; inclusive: boolean } {\n switch (model) {\n case \"rectilinear\":\n case \"fisheye-stereographic\":\n return { radiusMm: Number.POSITIVE_INFINITY, inclusive: false };\n case \"fisheye-equidistant\":\n return { radiusMm: Math.PI * focalLengthMm, inclusive: false };\n case \"fisheye-equisolid-angle\":\n return { radiusMm: 2 * focalLengthMm, inclusive: false };\n case \"fisheye-orthographic\":\n return { radiusMm: focalLengthMm, inclusive: true };\n }\n}\n\n/** Inverse theta(r) for one radial model; throws outside the image circle. */\nexport function radialProjectionFieldAngle(\n model: RadialLensProjectionModel,\n focalLengthMm: number,\n imageRadiusMm: number\n): number {\n const limit = radialImageRadiusLimit(model, focalLengthMm);\n if (\n imageRadiusMm < 0 ||\n imageRadiusMm > limit.radiusMm ||\n (!limit.inclusive && imageRadiusMm === limit.radiusMm)\n ) {\n throw new InvalidScientificInputError(\n `Image radius lies outside the ${model} image circle.`\n );\n }\n switch (model) {\n case \"rectilinear\":\n return Math.atan(imageRadiusMm / focalLengthMm);\n case \"fisheye-equidistant\":\n return imageRadiusMm / focalLengthMm;\n case \"fisheye-equisolid-angle\":\n return 2 * Math.asin(imageRadiusMm / (2 * focalLengthMm));\n case \"fisheye-stereographic\":\n return 2 * Math.atan(imageRadiusMm / (2 * focalLengthMm));\n case \"fisheye-orthographic\":\n return Math.asin(Math.min(1, imageRadiusMm / focalLengthMm));\n }\n}\n\nfunction assumptions(model: LensProjectionModel): readonly string[] {\n const common = [\n \"Ideal mapping function of a perfect projection; real lenses deviate from it and need calibrated distortion data\",\n \"Camera frame +X right, +Y up, +Z toward the scene; image plane +X right, +Y up (non-inverted)\"\n ];\n if (model === \"equirectangular\") {\n return [\n \"Equirectangular (spherical) projection: x = f * longitude, y = f * latitude, longitude measured about +Y from +Z\",\n ...common\n ];\n }\n return [\n `Radial projection ${model}; image azimuth equals scene azimuth about the optical axis`,\n ...common\n ];\n}\n\nfunction validateCommon(\n input: { projectionModel: unknown; focalLengthMm: number },\n name: string\n): LensProjectionModel {\n requireRecord(name, input);\n const model = parseLensProjectionModel(input.projectionModel);\n requirePositiveFinite(\"focalLengthMm\", input.focalLengthMm);\n return model;\n}\n\n/**\n * Maps one camera-frame scene direction to its ideal image-plane point under the declared\n * projection model.\n */\nexport function calculateLensProjectionImagePoint(\n input: CalculateLensProjectionImagePointInput\n): CalculationResult<LensProjectionImagePoint> {\n requireInputKeys(input, \"calculateLensProjectionImagePoint\", [\"projectionModel\", \"focalLengthMm\", \"direction\"]);\n const model = validateCommon(input, \"input\");\n requireRecord(\"direction\", input.direction);\n rejectUnknownFields(input.direction, [\"x\", \"y\", \"z\"], \"direction\");\n const x = requireFinite(\"direction.x\", input.direction.x);\n const y = requireFinite(\"direction.y\", input.direction.y);\n const z = requireFinite(\"direction.z\", input.direction.z);\n const length = Math.hypot(x, y, z);\n if (!(length > 0) || !Number.isFinite(length)) {\n throw new InvalidScientificInputError(\n \"direction must be a finite non-zero vector.\"\n );\n }\n const { imagePointMm, fieldAngleRadians } = lensProjectionImagePointValue(\n model,\n input.focalLengthMm,\n x,\n y,\n z\n );\n\n return calculatedResult(\n {\n projectionModel: model,\n imagePointMm,\n fieldAngleRadians,\n imageRadiusMm: Math.hypot(imagePointMm.x, imagePointMm.y)\n },\n `${model}-lens-projection`,\n \"1.0.0\",\n assumptions(model)\n );\n}\n\n/**\n * Inverse-maps one image-plane point to its unit camera-frame scene direction under the declared\n * projection model. It rejects points outside the model's image circle. For equirectangular, it\n * rejects points outside +/-pi longitude and +/-pi/2 latitude.\n */\nexport function calculateLensProjectionDirection(\n input: CalculateLensProjectionDirectionInput\n): CalculationResult<LensProjectionDirection> {\n requireInputKeys(input, \"calculateLensProjectionDirection\", [\"projectionModel\", \"focalLengthMm\", \"imagePointMm\"]);\n const model = validateCommon(input, \"input\");\n requireRecord(\"imagePointMm\", input.imagePointMm);\n rejectUnknownFields(input.imagePointMm, [\"x\", \"y\"], \"imagePointMm\");\n const px = requireFinite(\"imagePointMm.x\", input.imagePointMm.x);\n const py = requireFinite(\"imagePointMm.y\", input.imagePointMm.y);\n const imageRadiusMm = Math.hypot(px, py);\n const direction = lensProjectionDirectionValue(\n model,\n input.focalLengthMm,\n px,\n py\n );\n\n return calculatedResult(\n {\n projectionModel: model,\n direction,\n fieldAngleRadians: Math.atan2(\n Math.hypot(direction.x, direction.y),\n direction.z\n ),\n imageRadiusMm\n },\n `inverse-${model}-lens-projection`,\n \"1.0.0\",\n assumptions(model)\n );\n}\n\n/** Signed angle subtended along one axis through the optical axis for a signed coordinate. */\nfunction signedAxisAngle(\n model: LensProjectionModel,\n focalLengthMm: number,\n coordinateMm: number\n): number {\n if (model === \"equirectangular\") {\n // Along a horizontal or vertical line through the centre the angle is linear in position.\n return coordinateMm / focalLengthMm;\n }\n const theta = radialProjectionFieldAngle(\n model,\n focalLengthMm,\n Math.abs(coordinateMm)\n );\n return coordinateMm < 0 ? -theta : theta;\n}\n\n/**\n * Angular field of view across a centred sensor dimension along one axis through the optical\n * axis: 2 * theta(d / 2) for radial models and d / f for equirectangular.\n *\n * For equirectangular, the result is the longitude span for a horizontal dimension and the latitude\n * span for a vertical one. A sensor dimension larger than a fisheye's image circle is rejected, not\n * clipped.\n */\nexport function calculateLensProjectionFieldOfView(\n input: CalculateLensProjectionFieldOfViewInput\n): CalculationResult<LensProjectionFieldOfView> {\n requireInputKeys(input, \"calculateLensProjectionFieldOfView\", [\"projectionModel\", \"focalLengthMm\", \"sensorDimensionMm\"]);\n const model = validateCommon(input, \"input\");\n requirePositiveFinite(\"sensorDimensionMm\", input.sensorDimensionMm);\n const radians =\n 2 *\n signedAxisAngle(model, input.focalLengthMm, input.sensorDimensionMm / 2);\n if (model === \"equirectangular\" && radians > 2 * Math.PI) {\n throw new InvalidScientificInputError(\n \"sensorDimensionMm exceeds the full 360-degree equirectangular span.\"\n );\n }\n return calculatedResult(\n {\n projectionModel: model,\n radians,\n degrees: (radians * 180) / Math.PI,\n projectionDistanceMm: input.focalLengthMm\n },\n `${model}-field-of-view`,\n \"1.0.0\",\n [\n ...assumptions(model),\n \"Field of view is measured along one axis through the optical axis\"\n ]\n );\n}\n\n/**\n * Asymmetric angular span between two signed sensor coordinates on one axis through the optical\n * axis, for off-centre crops.\n */\nexport function calculateLensProjectionFieldOfViewBounds(\n input: CalculateLensProjectionFieldOfViewBoundsInput\n): CalculationResult<LensProjectionFieldOfViewBounds> {\n requireInputKeys(input, \"calculateLensProjectionFieldOfViewBounds\", [\"projectionModel\", \"focalLengthMm\", \"minimumSensorCoordinateMm\", \"maximumSensorCoordinateMm\"]);\n const model = validateCommon(input, \"input\");\n const minimum = requireFinite(\n \"minimumSensorCoordinateMm\",\n input.minimumSensorCoordinateMm\n );\n const maximum = requireFinite(\n \"maximumSensorCoordinateMm\",\n input.maximumSensorCoordinateMm\n );\n if (maximum <= minimum) {\n throw new InvalidScientificInputError(\n \"maximumSensorCoordinateMm must be greater than minimumSensorCoordinateMm.\"\n );\n }\n const minimumRadians = signedAxisAngle(model, input.focalLengthMm, minimum);\n const maximumRadians = signedAxisAngle(model, input.focalLengthMm, maximum);\n const radians = maximumRadians - minimumRadians;\n if (model === \"equirectangular\" && radians > 2 * Math.PI) {\n throw new InvalidScientificInputError(\n \"Sensor bounds exceed the full 360-degree equirectangular span.\"\n );\n }\n return calculatedResult(\n {\n projectionModel: model,\n minimumRadians,\n maximumRadians,\n radians,\n minimumDegrees: (minimumRadians * 180) / Math.PI,\n maximumDegrees: (maximumRadians * 180) / Math.PI,\n degrees: (radians * 180) / Math.PI,\n projectionDistanceMm: input.focalLengthMm\n },\n `asymmetric-${model}-field-of-view`,\n \"1.0.0\",\n [\n ...assumptions(model),\n \"Signed sensor-plane bounds are measured relative to the optical axis along one axis through it\"\n ]\n );\n}\n\n/**\n * @internal Image point of a non-zero camera-frame direction under one model (no envelope).\n * Shared by the public mapping, geometric remaps and the environment ray query.\n */\nexport function lensProjectionImagePointValue(\n model: LensProjectionModel,\n focalLengthMm: number,\n x: number,\n y: number,\n z: number\n): { imagePointMm: { x: number; y: number }; fieldAngleRadians: number } {\n const length = Math.hypot(x, y, z);\n const f = focalLengthMm;\n const transverse = Math.hypot(x, y);\n const fieldAngleRadians = Math.atan2(transverse, z);\n\n let imagePointMm: { x: number; y: number };\n if (model === \"equirectangular\") {\n const latitude = Math.asin(Math.max(-1, Math.min(1, y / length)));\n const horizontal = Math.hypot(x, z);\n if (horizontal === 0) {\n // Poles have an undefined longitude; the projection is singular there.\n throw new InvalidScientificInputError(\n \"Equirectangular projection is undefined at the poles (direction parallel to +/-Y).\"\n );\n }\n const longitude = Math.atan2(x, z);\n imagePointMm = { x: f * longitude, y: f * latitude };\n } else {\n const limit = radialFieldAngleLimit(model);\n if (\n fieldAngleRadians > limit.radians ||\n (!limit.inclusive && fieldAngleRadians === limit.radians)\n ) {\n throw new InvalidScientificInputError(\n `direction lies outside the ${model} projection domain.`\n );\n }\n const radius = radialProjectionImageRadius(model, f, fieldAngleRadians);\n imagePointMm =\n transverse === 0\n ? { x: 0, y: 0 }\n : { x: (radius * x) / transverse, y: (radius * y) / transverse };\n }\n\n return { imagePointMm, fieldAngleRadians };\n}\n\n/** @internal Unit camera-frame direction of one image point under one model (no envelope). */\nexport function lensProjectionDirectionValue(\n model: LensProjectionModel,\n focalLengthMm: number,\n px: number,\n py: number\n): LensDirection {\n const f = focalLengthMm;\n const imageRadiusMm = Math.hypot(px, py);\n\n let direction: LensDirection;\n if (model === \"equirectangular\") {\n const longitude = px / f;\n const latitude = py / f;\n if (Math.abs(longitude) > Math.PI || Math.abs(latitude) > HALF_PI) {\n throw new InvalidScientificInputError(\n \"imagePointMm lies outside the equirectangular longitude/latitude domain.\"\n );\n }\n const cosLatitude = Math.cos(latitude);\n direction = {\n x: cosLatitude * Math.sin(longitude),\n y: Math.sin(latitude),\n z: cosLatitude * Math.cos(longitude)\n };\n } else {\n const theta = radialProjectionFieldAngle(model, f, imageRadiusMm);\n const sinTheta = Math.sin(theta);\n direction =\n imageRadiusMm === 0\n ? { x: 0, y: 0, z: 1 }\n : {\n x: (sinTheta * px) / imageRadiusMm,\n y: (sinTheta * py) / imageRadiusMm,\n z: Math.cos(theta)\n };\n }\n\n return direction;\n}\n\n/** d r / d theta of a radial model. */\nfunction radialDerivative(\n model: RadialLensProjectionModel,\n f: number,\n theta: number\n): number {\n switch (model) {\n case \"rectilinear\":\n return f / Math.cos(theta) ** 2;\n case \"fisheye-equidistant\":\n return f;\n case \"fisheye-equisolid-angle\":\n return f * Math.cos(theta / 2);\n case \"fisheye-stereographic\":\n return f / Math.cos(theta / 2) ** 2;\n case \"fisheye-orthographic\":\n return f * Math.cos(theta);\n }\n}\n\ntype Matrix32 = readonly [readonly [number, number], readonly [number, number], readonly [number, number]];\n\n/** Unit direction of an image point and its derivative d(direction)/d(point) (3 x 2). */\nfunction directionWithDerivative(\n model: LensProjectionModel,\n f: number,\n px: number,\n py: number\n): { direction: LensDirection; derivative: Matrix32 } {\n const direction = lensProjectionDirectionValue(model, f, px, py);\n if (model === \"equirectangular\") {\n const lambda = px / f;\n const phi = py / f;\n const cp = Math.cos(phi);\n const sp = Math.sin(phi);\n const cl = Math.cos(lambda);\n const sl = Math.sin(lambda);\n return {\n direction,\n derivative: [\n [(cp * cl) / f, (-sp * sl) / f],\n [0, cp / f],\n [(-cp * sl) / f, (-sp * cl) / f]\n ]\n };\n }\n const rho = Math.hypot(px, py);\n if (rho === 0) {\n const a = 1 / radialDerivative(model, f, 0);\n return { direction, derivative: [[a, 0], [0, a], [0, 0]] };\n }\n const theta = radialProjectionFieldAngle(model, f, rho);\n const dTheta = 1 / radialDerivative(model, f, theta);\n const a = Math.sin(theta) / rho;\n const aPrime = (Math.cos(theta) * dTheta * rho - Math.sin(theta)) / (rho * rho);\n const ux = px / rho;\n const uy = py / rho;\n const dz = -Math.sin(theta) * dTheta;\n return {\n direction,\n derivative: [\n [a + aPrime * px * ux, aPrime * px * uy],\n [aPrime * py * ux, a + aPrime * py * uy],\n [dz * ux, dz * uy]\n ]\n };\n}\n\n/** Image point of a unit direction and its derivative d(point)/d(direction) (2 x 3). */\nfunction imagePointWithDerivative(\n model: LensProjectionModel,\n f: number,\n v: LensDirection\n): { point: { x: number; y: number }; derivative: readonly [readonly [number, number, number], readonly [number, number, number]] } {\n const point = lensProjectionImagePointValue(model, f, v.x, v.y, v.z).imagePointMm;\n if (model === \"equirectangular\") {\n const h2 = v.x * v.x + v.z * v.z;\n const c = Math.sqrt(Math.max(0, 1 - v.y * v.y));\n return {\n point,\n derivative: [\n [(f * v.z) / h2, 0, (-f * v.x) / h2],\n [0, f / c, 0]\n ]\n };\n }\n const t = Math.hypot(v.x, v.y);\n const theta = Math.atan2(t, v.z);\n if (theta < 1e-9) {\n const g = radialDerivative(model, f, 0);\n return { point, derivative: [[g, 0, 0], [0, g, 0]] };\n }\n const s = Math.sin(theta);\n const g = radialProjectionImageRadius(model, f, theta);\n const b = g / s;\n const bPrime = (radialDerivative(model, f, theta) * s - g * Math.cos(theta)) / (s * s);\n // q = b(theta) (vx, vy); on the unit sphere d theta = -d vz / sin theta.\n const k = -bPrime / s;\n return {\n point,\n derivative: [\n [b, 0, k * v.x],\n [0, b, k * v.y]\n ]\n };\n}\n\n/**\n * @internal Destination-to-source remap between two ideal projections: the destination point is\n * unprojected with the destination model and reprojected with the source model. Returns the\n * source point and the 2 x 2 Jacobian d(source)/d(destination), row-major.\n */\nexport function lensProjectionRemapValue(\n destinationModel: LensProjectionModel,\n destinationFocalLengthMm: number,\n sourceModel: LensProjectionModel,\n sourceFocalLengthMm: number,\n px: number,\n py: number\n): { sourcePointMm: { x: number; y: number }; jacobian: readonly [number, number, number, number] } {\n const inverse = directionWithDerivative(destinationModel, destinationFocalLengthMm, px, py);\n const forward = imagePointWithDerivative(sourceModel, sourceFocalLengthMm, inverse.direction);\n const d = inverse.derivative;\n const q = forward.derivative;\n const j = (row: 0 | 1, column: 0 | 1): number =>\n q[row][0] * d[0][column] + q[row][1] * d[1][column] + q[row][2] * d[2][column];\n return {\n sourcePointMm: forward.point,\n jacobian: [j(0, 0), j(0, 1), j(1, 0), j(1, 1)]\n };\n}\n\n/** @internal Signed angle along one axis through the optical axis (exported for sampling plans). */\nexport function lensProjectionSignedAxisAngle(\n model: LensProjectionModel,\n focalLengthMm: number,\n coordinateMm: number\n): number {\n return signedAxisAngle(model, focalLengthMm, coordinateMm);\n}\n"]}
|
|
@@ -1,10 +1,9 @@
|
|
|
1
1
|
/**
|
|
2
|
-
*
|
|
3
|
-
*
|
|
4
|
-
*
|
|
5
|
-
*
|
|
6
|
-
*
|
|
7
|
-
* limits.
|
|
2
|
+
* Projected size, on the sensor, of a flat object that faces the camera (fronto-parallel).
|
|
3
|
+
* - Without focusDistanceM, it uses ideal pinhole projection with the nominal focal length.
|
|
4
|
+
* - With focusDistanceM, it projects onto the ideal thin-lens sensor plane for that focus distance.
|
|
5
|
+
* @see docs/PHYSICS_FOUNDATION.md for the equations, units, coordinate conventions, known blockers
|
|
6
|
+
* and support limits.
|
|
8
7
|
*/
|
|
9
8
|
import { type CalculationResult } from "../core/calculation-result.js";
|
|
10
9
|
export interface CalculateProjectedObjectSizeInput {
|
|
@@ -29,14 +28,14 @@ export interface ProjectedObjectSize {
|
|
|
29
28
|
heightPixels?: number;
|
|
30
29
|
}
|
|
31
30
|
/**
|
|
32
|
-
* Calculates the projected size of a
|
|
31
|
+
* Calculates the projected size of a flat object that faces the camera
|
|
32
|
+
* (fronto-parallel).
|
|
33
33
|
*
|
|
34
|
-
* Without focusDistanceM,
|
|
35
|
-
*
|
|
36
|
-
*
|
|
34
|
+
* Without focusDistanceM, it uses ideal pinhole projection with the nominal
|
|
35
|
+
* focal length. With focusDistanceM, it projects onto the ideal thin-lens
|
|
36
|
+
* sensor plane for that focus distance.
|
|
37
37
|
*
|
|
38
38
|
* @param input Lens, object-size, distance, optional focus, and optional pixel-pitch inputs.
|
|
39
39
|
* @returns Projected object dimensions at the sensor plane.
|
|
40
40
|
*/
|
|
41
41
|
export declare function calculateProjectedObjectSize(input: CalculateProjectedObjectSizeInput): CalculationResult<ProjectedObjectSize>;
|
|
42
|
-
//# sourceMappingURL=projected-object-size.d.ts.map
|
|
@@ -1,26 +1,28 @@
|
|
|
1
1
|
// SPDX-License-Identifier: Apache-2.0
|
|
2
2
|
/**
|
|
3
|
-
*
|
|
4
|
-
*
|
|
5
|
-
*
|
|
6
|
-
*
|
|
7
|
-
*
|
|
8
|
-
* limits.
|
|
3
|
+
* Projected size, on the sensor, of a flat object that faces the camera (fronto-parallel).
|
|
4
|
+
* - Without focusDistanceM, it uses ideal pinhole projection with the nominal focal length.
|
|
5
|
+
* - With focusDistanceM, it projects onto the ideal thin-lens sensor plane for that focus distance.
|
|
6
|
+
* @see docs/PHYSICS_FOUNDATION.md for the equations, units, coordinate conventions, known blockers
|
|
7
|
+
* and support limits.
|
|
9
8
|
*/
|
|
10
9
|
import { calculatedResult } from "../core/calculation-result.js";
|
|
11
10
|
import { requirePositiveFinite } from "../core/validation.js";
|
|
12
11
|
import { calculateThinLensImageDistance } from "../optics/thin-lens.js";
|
|
12
|
+
import { requireInputKeys } from "../core/record-validation.js";
|
|
13
13
|
/**
|
|
14
|
-
* Calculates the projected size of a
|
|
14
|
+
* Calculates the projected size of a flat object that faces the camera
|
|
15
|
+
* (fronto-parallel).
|
|
15
16
|
*
|
|
16
|
-
* Without focusDistanceM,
|
|
17
|
-
*
|
|
18
|
-
*
|
|
17
|
+
* Without focusDistanceM, it uses ideal pinhole projection with the nominal
|
|
18
|
+
* focal length. With focusDistanceM, it projects onto the ideal thin-lens
|
|
19
|
+
* sensor plane for that focus distance.
|
|
19
20
|
*
|
|
20
21
|
* @param input Lens, object-size, distance, optional focus, and optional pixel-pitch inputs.
|
|
21
22
|
* @returns Projected object dimensions at the sensor plane.
|
|
22
23
|
*/
|
|
23
24
|
export function calculateProjectedObjectSize(input) {
|
|
25
|
+
requireInputKeys(input, "calculateProjectedObjectSize", ["focalLengthMm", "objectWidthM", "objectHeightM", "distanceM", "focusDistanceM", "pixelPitchMicrometers"]);
|
|
24
26
|
requirePositiveFinite("focalLengthMm", input.focalLengthMm);
|
|
25
27
|
requirePositiveFinite("objectWidthM", input.objectWidthM);
|
|
26
28
|
requirePositiveFinite("objectHeightM", input.objectHeightM);
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"projected-object-size.js","sourceRoot":"","sources":["../../src/camera/projected-object-size.ts"],"names":[],"mappings":"AAAA,sCAAsC;AAEtC
|
|
1
|
+
{"version":3,"file":"projected-object-size.js","sourceRoot":"","sources":["../../src/camera/projected-object-size.ts"],"names":[],"mappings":"AAAA,sCAAsC;AAEtC;;;;;;GAMG;AAEH,OAAO,EACL,gBAAgB,EAEjB,MAAM,+BAA+B,CAAC;AACvC,OAAO,EAAE,qBAAqB,EAAE,MAAM,uBAAuB,CAAC;AAC9D,OAAO,EAAE,8BAA8B,EAAE,MAAM,wBAAwB,CAAC;AACxE,OAAO,EAAE,gBAAgB,EAAE,MAAM,8BAA8B,CAAC;AAyBhE;;;;;;;;;;GAUG;AACH,MAAM,UAAU,4BAA4B,CAC1C,KAAwC;IAExC,gBAAgB,CAAC,KAAK,EAAE,8BAA8B,EAAE,CAAC,eAAe,EAAE,cAAc,EAAE,eAAe,EAAE,WAAW,EAAE,gBAAgB,EAAE,uBAAuB,CAAC,CAAC,CAAC;IACpK,qBAAqB,CAAC,eAAe,EAAE,KAAK,CAAC,aAAa,CAAC,CAAC;IAC5D,qBAAqB,CAAC,cAAc,EAAE,KAAK,CAAC,YAAY,CAAC,CAAC;IAC1D,qBAAqB,CAAC,eAAe,EAAE,KAAK,CAAC,aAAa,CAAC,CAAC;IAC5D,qBAAqB,CAAC,WAAW,EAAE,KAAK,CAAC,SAAS,CAAC,CAAC;IAEpD,MAAM,eAAe,GACnB,KAAK,CAAC,cAAc,KAAK,SAAS;QAChC,CAAC,CAAC,SAAS;QACX,CAAC,CAAC,8BAA8B,CAAC;YAC7B,aAAa,EAAE,KAAK,CAAC,aAAa;YAClC,eAAe,EAAE,KAAK,CAAC,cAAc;SACtC,CAAC,CAAC;IACT,MAAM,oBAAoB,GACxB,eAAe,EAAE,KAAK,CAAC,eAAe,IAAI,KAAK,CAAC,aAAa,CAAC;IAChE,MAAM,OAAO,GACX,oBAAoB,GAAG,CAAC,KAAK,CAAC,YAAY,GAAG,KAAK,CAAC,SAAS,CAAC,CAAC;IAChE,MAAM,QAAQ,GACZ,oBAAoB,GAAG,CAAC,KAAK,CAAC,aAAa,GAAG,KAAK,CAAC,SAAS,CAAC,CAAC;IACjE,MAAM,KAAK,GACT,eAAe,KAAK,SAAS;QAC3B,CAAC,CAAC,qCAAqC;QACvC,CAAC,CAAC,mCAAmC,CAAC;IAC1C,MAAM,WAAW,GACf,eAAe,KAAK,SAAS;QAC3B,CAAC,CAAC;YACE,0BAA0B;YAC1B,+CAA+C;YAC/C,uDAAuD;SACxD;QACH,CAAC,CAAC;YACE,kEAAkE;YAClE,+CAA+C;YAC/C,uDAAuD;YACvD,mEAAmE;SACpE,CAAC;IAER,IAAI,KAAK,CAAC,qBAAqB,KAAK,SAAS,EAAE,CAAC;QAC9C,OAAO,gBAAgB,CACrB,EAAE,OAAO,EAAE,QAAQ,EAAE,oBAAoB,EAAE,EAC3C,KAAK,EACL,OAAO,EACP,WAAW,CACZ,CAAC;IACJ,CAAC;IAED,qBAAqB,CACnB,uBAAuB,EACvB,KAAK,CAAC,qBAAqB,CAC5B,CAAC;IACF,MAAM,OAAO,GAAG,KAAK,CAAC,qBAAqB,GAAG,IAAI,CAAC;IAEnD,OAAO,gBAAgB,CACrB;QACE,OAAO;QACP,QAAQ;QACR,oBAAoB;QACpB,WAAW,EAAE,OAAO,GAAG,OAAO;QAC9B,YAAY,EAAE,QAAQ,GAAG,OAAO;KACjC,EACD,KAAK,EACL,OAAO,EACP,WAAW,CACZ,CAAC;AACJ,CAAC","sourcesContent":["// SPDX-License-Identifier: Apache-2.0\n\n/**\n * Projected size, on the sensor, of a flat object that faces the camera (fronto-parallel).\n * - Without focusDistanceM, it uses ideal pinhole projection with the nominal focal length.\n * - With focusDistanceM, it projects onto the ideal thin-lens sensor plane for that focus distance.\n * @see docs/PHYSICS_FOUNDATION.md for the equations, units, coordinate conventions, known blockers\n * and support limits.\n */\n\nimport {\n calculatedResult,\n type CalculationResult\n} from \"../core/calculation-result.js\";\nimport { requirePositiveFinite } from \"../core/validation.js\";\nimport { calculateThinLensImageDistance } from \"../optics/thin-lens.js\";\nimport { requireInputKeys } from \"../core/record-validation.js\";\n\nexport interface CalculateProjectedObjectSizeInput {\n /** Lens focal length in millimetres. */\n focalLengthMm: number;\n /** Object width in metres. */\n objectWidthM: number;\n /** Object height in metres. */\n objectHeightM: number;\n /** Object-plane distance from the camera in metres. */\n distanceM: number;\n /** Optional focus distance in metres for focus-aware sensor-plane projection. */\n focusDistanceM?: number;\n /** Optional sensor pixel pitch in micrometres. */\n pixelPitchMicrometers?: number;\n}\n\nexport interface ProjectedObjectSize {\n widthMm: number;\n heightMm: number;\n projectionDistanceMm: number;\n widthPixels?: number;\n heightPixels?: number;\n}\n\n/**\n * Calculates the projected size of a flat object that faces the camera\n * (fronto-parallel).\n *\n * Without focusDistanceM, it uses ideal pinhole projection with the nominal\n * focal length. With focusDistanceM, it projects onto the ideal thin-lens\n * sensor plane for that focus distance.\n *\n * @param input Lens, object-size, distance, optional focus, and optional pixel-pitch inputs.\n * @returns Projected object dimensions at the sensor plane.\n */\nexport function calculateProjectedObjectSize(\n input: CalculateProjectedObjectSizeInput\n): CalculationResult<ProjectedObjectSize> {\n requireInputKeys(input, \"calculateProjectedObjectSize\", [\"focalLengthMm\", \"objectWidthM\", \"objectHeightM\", \"distanceM\", \"focusDistanceM\", \"pixelPitchMicrometers\"]);\n requirePositiveFinite(\"focalLengthMm\", input.focalLengthMm);\n requirePositiveFinite(\"objectWidthM\", input.objectWidthM);\n requirePositiveFinite(\"objectHeightM\", input.objectHeightM);\n requirePositiveFinite(\"distanceM\", input.distanceM);\n\n const focusProjection =\n input.focusDistanceM === undefined\n ? undefined\n : calculateThinLensImageDistance({\n focalLengthMm: input.focalLengthMm,\n objectDistanceM: input.focusDistanceM\n });\n const projectionDistanceMm =\n focusProjection?.value.imageDistanceMm ?? input.focalLengthMm;\n const widthMm =\n projectionDistanceMm * (input.objectWidthM / input.distanceM);\n const heightMm =\n projectionDistanceMm * (input.objectHeightM / input.distanceM);\n const model =\n focusProjection === undefined\n ? \"fronto-parallel-pinhole-object-size\"\n : \"focus-aware-thin-lens-object-size\";\n const assumptions =\n focusProjection === undefined\n ? [\n \"Ideal pinhole projection\",\n \"Object plane is fronto-parallel to the sensor\",\n \"Physical object dimensions are supplied by the caller\"\n ]\n : [\n \"Ideal paraxial thin-lens projection to the selected sensor plane\",\n \"Object plane is fronto-parallel to the sensor\",\n \"Physical object dimensions are supplied by the caller\",\n \"Real-lens focus breathing and pupil magnification are not modeled\"\n ];\n\n if (input.pixelPitchMicrometers === undefined) {\n return calculatedResult(\n { widthMm, heightMm, projectionDistanceMm },\n model,\n \"1.0.0\",\n assumptions\n );\n }\n\n requirePositiveFinite(\n \"pixelPitchMicrometers\",\n input.pixelPitchMicrometers\n );\n const pitchMm = input.pixelPitchMicrometers / 1000;\n\n return calculatedResult(\n {\n widthMm,\n heightMm,\n projectionDistanceMm,\n widthPixels: widthMm / pitchMm,\n heightPixels: heightMm / pitchMm\n },\n model,\n \"1.0.0\",\n assumptions\n );\n}\n"]}
|