@photivra/engine 2.18.0 → 2.19.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 +68 -1
- package/CITATION.cff +1 -1
- package/README.md +6 -6
- package/SECURITY.md +1 -1
- package/dist/capture/focus-control.js +2 -75
- package/dist/capture/focus-control.js.map +1 -1
- package/dist/capture/native-environment-lean.d.ts +1 -0
- package/dist/capture/native-environment-lean.js +1 -1
- package/dist/capture/native-environment-lean.js.map +1 -1
- package/dist/capture/native-environment-optical-stage.d.ts +1 -0
- package/dist/capture/native-environment-optical-stage.js +2 -5
- package/dist/capture/native-environment-optical-stage.js.map +1 -1
- package/dist/capture/native-environment-raw.js +1 -5
- package/dist/capture/native-environment-raw.js.map +1 -1
- package/dist/capture/release-sequence.js +2 -47
- package/dist/capture/release-sequence.js.map +1 -1
- package/dist/color/white-balance.d.ts +2 -0
- package/dist/color/white-balance.js +3 -56
- package/dist/color/white-balance.js.map +1 -1
- package/dist/composition/image-formation-plan.d.ts +1 -0
- package/dist/composition/image-formation-plan.js +3 -49
- package/dist/composition/image-formation-plan.js.map +1 -1
- package/dist/core/evidence-provenance.js +1 -16
- package/dist/core/evidence-provenance.js.map +1 -1
- package/dist/core/record-validation.d.ts +54 -0
- package/dist/core/record-validation.js +176 -0
- package/dist/core/record-validation.js.map +1 -1
- package/dist/core/scientific-assurance.js +1 -18
- package/dist/core/scientific-assurance.js.map +1 -1
- package/dist/core/shared-helpers.d.ts +33 -0
- package/dist/core/shared-helpers.js +34 -0
- package/dist/core/shared-helpers.js.map +1 -0
- package/dist/core/spectral-composition.js +1 -36
- package/dist/core/spectral-composition.js.map +1 -1
- package/dist/core/spectral.js +1 -19
- package/dist/core/spectral.js.map +1 -1
- package/dist/core/version.d.ts +1 -1
- package/dist/core/version.js +1 -1
- package/dist/core/version.js.map +1 -1
- package/dist/equipment/exposure-capabilities.d.ts +1 -0
- package/dist/equipment/exposure-capabilities.js +2 -36
- package/dist/equipment/exposure-capabilities.js.map +1 -1
- package/dist/equipment/iso-capabilities.js +2 -49
- package/dist/equipment/iso-capabilities.js.map +1 -1
- package/dist/equipment/metering-capabilities.js +1 -26
- package/dist/equipment/metering-capabilities.js.map +1 -1
- package/dist/equipment/release-capabilities.js +1 -53
- package/dist/equipment/release-capabilities.js.map +1 -1
- package/dist/exposure/auto-iso-slowest-shutter.js +1 -7
- package/dist/exposure/auto-iso-slowest-shutter.js.map +1 -1
- package/dist/exposure/exposure-duration-control.js +1 -16
- package/dist/exposure/exposure-duration-control.js.map +1 -1
- package/dist/exposure/exposure-mode-resolver.js +1 -17
- package/dist/exposure/exposure-mode-resolver.js.map +1 -1
- package/dist/exposure/filtered-exposure-time.d.ts +93 -0
- package/dist/exposure/filtered-exposure-time.js +129 -0
- package/dist/exposure/filtered-exposure-time.js.map +1 -0
- package/dist/exposure/flash-ttl.d.ts +1 -0
- package/dist/exposure/flash-ttl.js +1 -1
- package/dist/exposure/flash-ttl.js.map +1 -1
- package/dist/exposure/flash.js +1 -49
- package/dist/exposure/flash.js.map +1 -1
- package/dist/exposure/metering-scene-radiance.js +1 -25
- package/dist/exposure/metering-scene-radiance.js.map +1 -1
- package/dist/exposure/metering-target.js +1 -30
- package/dist/exposure/metering-target.js.map +1 -1
- package/dist/exposure/metering-temporal.js +1 -8
- package/dist/exposure/metering-temporal.js.map +1 -1
- package/dist/exposure/metering.js +1 -72
- package/dist/exposure/metering.js.map +1 -1
- package/dist/exposure/program-line.js +1 -45
- package/dist/exposure/program-line.js.map +1 -1
- package/dist/facade/develop-joined-parts.d.ts +29 -0
- package/dist/facade/develop-joined-parts.js +33 -0
- package/dist/facade/develop-joined-parts.js.map +1 -0
- package/dist/facade/generic-lens-capture.d.ts +4 -2
- package/dist/facade/generic-lens-capture.js +4 -2
- package/dist/facade/generic-lens-capture.js.map +1 -1
- package/dist/facade/simulate-capture.d.ts +37 -5
- package/dist/facade/simulate-capture.js +153 -96
- package/dist/facade/simulate-capture.js.map +1 -1
- package/dist/gpu/chart-composite-gpu.js +1 -3
- package/dist/gpu/chart-composite-gpu.js.map +1 -1
- package/dist/gpu/chart-radiance-gpu.js +1 -5
- package/dist/gpu/chart-radiance-gpu.js.map +1 -1
- package/dist/gpu/display-view-quality-gpu.d.ts +13 -1
- package/dist/gpu/display-view-quality-gpu.js +4 -8
- package/dist/gpu/display-view-quality-gpu.js.map +1 -1
- package/dist/gpu/display-view-speed-gpu.js +3 -25
- package/dist/gpu/display-view-speed-gpu.js.map +1 -1
- package/dist/gpu/sensor-stage-gpu.js +1 -5
- package/dist/gpu/sensor-stage-gpu.js.map +1 -1
- package/dist/gpu/webgpu-runtime.d.ts +2 -0
- package/dist/gpu/webgpu-runtime.js +3 -0
- package/dist/gpu/webgpu-runtime.js.map +1 -1
- package/dist/index.d.ts +4 -1
- package/dist/index.js +3 -0
- package/dist/index.js.map +1 -1
- package/dist/motion/camera-rotation.js +1 -6
- package/dist/motion/camera-rotation.js.map +1 -1
- package/dist/motion/capture-rotation-inverse-mapping.d.ts +12 -0
- package/dist/motion/capture-rotation-inverse-mapping.js +2 -2
- package/dist/motion/capture-rotation-inverse-mapping.js.map +1 -1
- package/dist/motion/capture-rotation-temporal-quadrature.d.ts +1 -0
- package/dist/motion/capture-rotation-temporal-quadrature.js +1 -1
- package/dist/motion/capture-rotation-temporal-quadrature.js.map +1 -1
- package/dist/motion/capture-rotation-trajectory.js +2 -17
- package/dist/motion/capture-rotation-trajectory.js.map +1 -1
- package/dist/motion/capture-translation-parallax-temporal-quadrature.d.ts +1 -0
- package/dist/motion/capture-translation-parallax-temporal-quadrature.js +3 -14
- package/dist/motion/capture-translation-parallax-temporal-quadrature.js.map +1 -1
- package/dist/motion/extended-object-projection.js +5 -40
- package/dist/motion/extended-object-projection.js.map +1 -1
- package/dist/optics/atmospheric-haze.js +1 -7
- package/dist/optics/atmospheric-haze.js.map +1 -1
- package/dist/optics/brown-conrady-distortion.js +1 -7
- package/dist/optics/brown-conrady-distortion.js.map +1 -1
- package/dist/optics/complex-pupil-psf.d.ts +1 -0
- package/dist/optics/complex-pupil-psf.js +2 -84
- package/dist/optics/complex-pupil-psf.js.map +1 -1
- package/dist/optics/focus-state.js +1 -11
- package/dist/optics/focus-state.js.map +1 -1
- package/dist/optics/front-of-lens-filter.d.ts +5 -0
- package/dist/optics/front-of-lens-filter.js +3 -65
- package/dist/optics/front-of-lens-filter.js.map +1 -1
- package/dist/optics/generic-nd-filter-presets.d.ts +12 -0
- package/dist/optics/generic-nd-filter-presets.js +48 -0
- package/dist/optics/generic-nd-filter-presets.js.map +1 -0
- package/dist/optics/illumination-vignetting.js +1 -6
- package/dist/optics/illumination-vignetting.js.map +1 -1
- package/dist/optics/lens-psf-profile.d.ts +4 -1
- package/dist/optics/lens-psf-profile.js +12 -111
- package/dist/optics/lens-psf-profile.js.map +1 -1
- package/dist/optics/longitudinal-chromatic-aberration.js +1 -7
- package/dist/optics/longitudinal-chromatic-aberration.js.map +1 -1
- package/dist/optics/pupil-vignetting.js +1 -7
- package/dist/optics/pupil-vignetting.js.map +1 -1
- package/dist/optics/radial-distortion.js +1 -6
- package/dist/optics/radial-distortion.js.map +1 -1
- package/dist/optics/scene-to-sensor-irradiance.js +4 -96
- package/dist/optics/scene-to-sensor-irradiance.js.map +1 -1
- package/dist/optics/stray-light.d.ts +1 -0
- package/dist/optics/stray-light.js +1 -1
- package/dist/optics/stray-light.js.map +1 -1
- package/dist/optics/zernike-wavefront.js +1 -7
- package/dist/optics/zernike-wavefront.js.map +1 -1
- package/dist/output/capture-geometry.js +1 -8
- package/dist/output/capture-geometry.js.map +1 -1
- package/dist/output/developed-lens-corrections.d.ts +62 -0
- package/dist/output/developed-lens-corrections.js +135 -0
- package/dist/output/developed-lens-corrections.js.map +1 -0
- package/dist/output/generic-lens-corrections.d.ts +2 -6
- package/dist/output/generic-lens-corrections.js +3 -6
- package/dist/output/generic-lens-corrections.js.map +1 -1
- package/dist/output/geometric-transforms.js +1 -4
- package/dist/output/geometric-transforms.js.map +1 -1
- package/dist/output/native-capture-sdr.d.ts +2 -2
- package/dist/output/native-capture-sdr.js +3 -2
- package/dist/output/native-capture-sdr.js.map +1 -1
- package/dist/processing/development-detail.d.ts +29 -0
- package/dist/processing/development-detail.js +128 -107
- package/dist/processing/development-detail.js.map +1 -1
- package/dist/schema/illumination-temporal.js +3 -72
- package/dist/schema/illumination-temporal.js.map +1 -1
- package/dist/schema/illumination.d.ts +1 -0
- package/dist/schema/illumination.js +2 -65
- package/dist/schema/illumination.js.map +1 -1
- package/dist/schema/scene-radiance-temporal.js +2 -14
- package/dist/schema/scene-radiance-temporal.js.map +1 -1
- package/dist/schema/scene-radiance.js +2 -60
- package/dist/schema/scene-radiance.js.map +1 -1
- package/dist/schema/validation.d.ts +2 -0
- package/dist/schema/validation.js +2 -17
- package/dist/schema/validation.js.map +1 -1
- package/dist/sensor/accumulated-charge.js +2 -59
- package/dist/sensor/accumulated-charge.js.map +1 -1
- package/dist/sensor/architecture.js +1 -16
- package/dist/sensor/architecture.js.map +1 -1
- package/dist/sensor/camera-saturation-capacity.d.ts +1 -0
- package/dist/sensor/camera-saturation-capacity.js +3 -55
- package/dist/sensor/camera-saturation-capacity.js.map +1 -1
- package/dist/sensor/capture-color-sampling-binding.js +1 -26
- package/dist/sensor/capture-color-sampling-binding.js.map +1 -1
- package/dist/sensor/capture-mode-timing.js +1 -39
- package/dist/sensor/capture-mode-timing.js.map +1 -1
- package/dist/sensor/capture-mode.js +1 -23
- package/dist/sensor/capture-mode.js.map +1 -1
- package/dist/sensor/color-sampling.js +1 -26
- package/dist/sensor/color-sampling.js.map +1 -1
- package/dist/sensor/constant-rate-temporal-integration.js +2 -46
- package/dist/sensor/constant-rate-temporal-integration.js.map +1 -1
- package/dist/sensor/dark-current.js +2 -45
- package/dist/sensor/dark-current.js.map +1 -1
- package/dist/sensor/eqe-electron-rate.js +2 -35
- package/dist/sensor/eqe-electron-rate.js.map +1 -1
- package/dist/sensor/exposure-window.d.ts +5 -0
- package/dist/sensor/exposure-window.js +7 -22
- package/dist/sensor/exposure-window.js.map +1 -1
- package/dist/sensor/iso-gain.js +1 -7
- package/dist/sensor/iso-gain.js.map +1 -1
- package/dist/sensor/iso-signal-chain.js +1 -43
- package/dist/sensor/iso-signal-chain.js.map +1 -1
- package/dist/sensor/optical-stack.js +1 -25
- package/dist/sensor/optical-stack.js.map +1 -1
- package/dist/sensor/photon-energy.js +1 -26
- package/dist/sensor/photon-energy.js.map +1 -1
- package/dist/sensor/physical-charge-capacity.js +3 -77
- package/dist/sensor/physical-charge-capacity.js.map +1 -1
- package/dist/sensor/radiometry-readiness.js +2 -23
- package/dist/sensor/radiometry-readiness.js.map +1 -1
- package/dist/sensor/raw-readout.d.ts +3 -0
- package/dist/sensor/raw-readout.js +4 -66
- package/dist/sensor/raw-readout.js.map +1 -1
- package/dist/sensor/raw-reconstruction.js +2 -64
- package/dist/sensor/raw-reconstruction.js.map +1 -1
- package/dist/sensor/readout-exposure-linkage.js +1 -9
- package/dist/sensor/readout-exposure-linkage.js.map +1 -1
- package/dist/sensor/readout-timing.js +3 -57
- package/dist/sensor/readout-timing.js.map +1 -1
- package/dist/sensor/response-application-compatibility.d.ts +2 -0
- package/dist/sensor/response-application-compatibility.js +3 -29
- package/dist/sensor/response-application-compatibility.js.map +1 -1
- package/dist/sensor/response-operating-range.d.ts +1 -0
- package/dist/sensor/response-operating-range.js +3 -79
- package/dist/sensor/response-operating-range.js.map +1 -1
- package/dist/sensor/responsivity-photocurrent.js +4 -108
- package/dist/sensor/responsivity-photocurrent.js.map +1 -1
- package/dist/sensor/sampling-aperture.js +1 -25
- package/dist/sensor/sampling-aperture.js.map +1 -1
- package/dist/sensor/spatial-sample-reduction.js +2 -19
- package/dist/sensor/spatial-sample-reduction.js.map +1 -1
- package/dist/sensor/spatial-sampling-quadrature.js +1 -3
- package/dist/sensor/spatial-sampling-quadrature.js.map +1 -1
- package/dist/sensor/spatio-spectral-reduction.js +1 -18
- package/dist/sensor/spatio-spectral-reduction.js.map +1 -1
- package/dist/sensor/spectral-coverage.d.ts +10 -1
- package/dist/sensor/spectral-coverage.js +1 -1
- package/dist/sensor/spectral-coverage.js.map +1 -1
- package/dist/sensor/spectral-quadrature.js +2 -35
- package/dist/sensor/spectral-quadrature.js.map +1 -1
- package/dist/sensor/spectral-response.js +1 -47
- package/dist/sensor/spectral-response.js.map +1 -1
- package/dist/stabilization/camera-shake.js +1 -6
- package/dist/stabilization/camera-shake.js.map +1 -1
- package/dist/stabilization/system.js +2 -80
- package/dist/stabilization/system.js.map +1 -1
- package/docs/AGENT_GUIDE.md +1 -0
- package/docs/API_REFERENCE.md +41 -2
- package/docs/QUICK_START.md +90 -8
- package/docs/USAGE.md +47 -2
- package/docs/api/core-version.md +1 -1
- package/docs/api/exports.json +53 -3
- package/docs/api/exposure-filtered-exposure-time.md +105 -0
- package/docs/api/facade-develop-joined-parts.md +32 -0
- package/docs/api/facade-simulate-capture.md +36 -5
- package/docs/api/optics-generic-nd-filter-presets.md +34 -0
- package/docs/api/optics-lens-psf-profile.md +3 -1
- package/docs/api/output-developed-lens-corrections.md +12 -0
- package/docs/api/output-generic-lens-corrections.md +0 -9
- package/llms.txt +1 -0
- package/package.json +1 -1
|
@@ -8,64 +8,19 @@
|
|
|
8
8
|
* @see docs/SCENE_RADIANCE_AND_ILLUMINATION.md for equations, coordinate/unit conventions, blockers
|
|
9
9
|
* and support limits.
|
|
10
10
|
*/
|
|
11
|
-
import { rejectUnknownFields, rejectUnknownVariantFields, requireFixedFieldsWhenPresent } from "../core/record-validation.js";
|
|
11
|
+
import { rejectUnknownFields, rejectUnknownVariantFields, requireFixedFieldsWhenPresent, requireConfigRecord as requireRecord, requireTrimmedConfigString as requireNonEmptyString, parseConfigScientificStatus as parseScientificStatus, requireConfigFiniteNumber as requireFinite, parseConfigLimitations as parseLimitations, requireConfigFraction as requireFraction, requireConfigNumberAtLeastZero as requireNonNegativeFinite, requireConfigNumberAboveZero as requirePositiveFinite } from "../core/record-validation.js";
|
|
12
12
|
import { InvalidConfigurationError } from "../core/configuration-error.js";
|
|
13
13
|
import { parseEvidenceList } from "../core/evidence-provenance.js";
|
|
14
14
|
import { parseSpectralWavelengthBasis } from "../core/spectral.js";
|
|
15
15
|
import { parseNormalizedDiscreteSpectralLineDistribution } from "../core/spectral-composition.js";
|
|
16
16
|
export const SCENE_ILLUMINATION_PROFILE_SCHEMA_VERSION = "0.1.0";
|
|
17
|
-
function requireRecord(value, path, allowedKeys) {
|
|
18
|
-
if (typeof value !== "object" ||
|
|
19
|
-
value === null ||
|
|
20
|
-
Array.isArray(value)) {
|
|
21
|
-
throw new InvalidConfigurationError(path + " must be an object.");
|
|
22
|
-
}
|
|
23
|
-
if (allowedKeys !== null)
|
|
24
|
-
rejectUnknownFields(value, allowedKeys, path);
|
|
25
|
-
return value;
|
|
26
|
-
}
|
|
27
|
-
function requireNonEmptyString(value, path) {
|
|
28
|
-
if (typeof value !== "string" ||
|
|
29
|
-
value.trim().length === 0) {
|
|
30
|
-
throw new InvalidConfigurationError(path + " must be a non-empty string.");
|
|
31
|
-
}
|
|
32
|
-
return value.trim();
|
|
33
|
-
}
|
|
34
17
|
function requireBoolean(value, path) {
|
|
35
18
|
if (typeof value !== "boolean") {
|
|
36
19
|
throw new InvalidConfigurationError(path + " must be a boolean.");
|
|
37
20
|
}
|
|
38
21
|
return value;
|
|
39
22
|
}
|
|
40
|
-
function
|
|
41
|
-
if (typeof value !== "number" ||
|
|
42
|
-
!Number.isFinite(value)) {
|
|
43
|
-
throw new InvalidConfigurationError(path + " must be a finite number.");
|
|
44
|
-
}
|
|
45
|
-
return value;
|
|
46
|
-
}
|
|
47
|
-
function requirePositiveFinite(value, path) {
|
|
48
|
-
const number = requireFinite(value, path);
|
|
49
|
-
if (number <= 0) {
|
|
50
|
-
throw new InvalidConfigurationError(path + " must be greater than zero.");
|
|
51
|
-
}
|
|
52
|
-
return number;
|
|
53
|
-
}
|
|
54
|
-
function requireNonNegativeFinite(value, path) {
|
|
55
|
-
const number = requireFinite(value, path);
|
|
56
|
-
if (number < 0) {
|
|
57
|
-
throw new InvalidConfigurationError(path + " must be greater than or equal to zero.");
|
|
58
|
-
}
|
|
59
|
-
return number;
|
|
60
|
-
}
|
|
61
|
-
function requireFraction(value, path) {
|
|
62
|
-
const number = requireFinite(value, path);
|
|
63
|
-
if (number < 0 || number > 1) {
|
|
64
|
-
throw new InvalidConfigurationError(path + " must be a finite fraction from 0 through 1.");
|
|
65
|
-
}
|
|
66
|
-
return number;
|
|
67
|
-
}
|
|
68
|
-
function parseVector3(value, path) {
|
|
23
|
+
export function parseVector3(value, path) {
|
|
69
24
|
const record = requireRecord(value, path, ["x", "y", "z"]);
|
|
70
25
|
return {
|
|
71
26
|
x: requireFinite(record.x, path + ".x"),
|
|
@@ -82,13 +37,6 @@ function parseDirectionUnitVector(value, path) {
|
|
|
82
37
|
}
|
|
83
38
|
return vector;
|
|
84
39
|
}
|
|
85
|
-
function parseScientificStatus(value, path) {
|
|
86
|
-
if (value !== "calibrated" &&
|
|
87
|
-
value !== "approximation") {
|
|
88
|
-
throw new InvalidConfigurationError(path + " is invalid.");
|
|
89
|
-
}
|
|
90
|
-
return value;
|
|
91
|
-
}
|
|
92
40
|
function parseUncertainty(value, path) {
|
|
93
41
|
const record = requireRecord(value, path, null);
|
|
94
42
|
if (record.kind === "relative") {
|
|
@@ -418,17 +366,6 @@ function parseSpectrum(value, path) {
|
|
|
418
366
|
samples
|
|
419
367
|
};
|
|
420
368
|
}
|
|
421
|
-
function parseLimitations(value, path) {
|
|
422
|
-
if (!Array.isArray(value)) {
|
|
423
|
-
throw new InvalidConfigurationError(path + " must be an array.");
|
|
424
|
-
}
|
|
425
|
-
const limitations = value.map((entry, index) => requireNonEmptyString(entry, path + "[" + index + "]"));
|
|
426
|
-
if (new Set(limitations).size !==
|
|
427
|
-
limitations.length) {
|
|
428
|
-
throw new InvalidConfigurationError(path + " must not contain duplicates.");
|
|
429
|
-
}
|
|
430
|
-
return limitations;
|
|
431
|
-
}
|
|
432
369
|
function parseFamily(value, path) {
|
|
433
370
|
if (value !== "point" &&
|
|
434
371
|
value !== "spot" &&
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"illumination.js","sourceRoot":"","sources":["../../src/schema/illumination.ts"],"names":[],"mappings":"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","sourcesContent":["// SPDX-License-Identifier: Apache-2.0\n\n/**\n * Scene illumination profiles: the light sources in a scene, independent of any renderer.\n *\n * A profile describes sources only. It does not compute the light leaving surfaces\n * (outgoing scene radiance), material response, visibility or indirect light, and on its\n * own it does not justify photon or electron counts downstream.\n * @see docs/SCENE_RADIANCE_AND_ILLUMINATION.md for equations, coordinate/unit conventions, blockers\n * and support limits.\n */\n\nimport { rejectUnknownFields, rejectUnknownVariantFields, requireFixedFieldsWhenPresent } from \"../core/record-validation.js\";\nimport { InvalidConfigurationError } from \"../core/configuration-error.js\";\nimport {\n parseEvidenceList,\n type EvidenceProvenance\n} from \"../core/evidence-provenance.js\";\nimport {\n parseSpectralWavelengthBasis,\n type SpectralWavelengthBasis\n} from \"../core/spectral.js\";\nimport {\n parseNormalizedDiscreteSpectralLineDistribution,\n type NormalizedDiscreteSpectralLineDistribution\n} from \"../core/spectral-composition.js\";\nimport type { Vector3 } from \"./scene.js\";\n\ntype UnknownRecord = Record<string, unknown>;\n\nexport const SCENE_ILLUMINATION_PROFILE_SCHEMA_VERSION = \"0.1.0\" as const;\n\nexport type SceneIlluminationSourceFamily =\n | \"point\"\n | \"spot\"\n | \"area\"\n | \"directional\"\n | \"environment\";\n\nexport type SceneIlluminationScientificStatus =\n | \"calibrated\"\n | \"approximation\";\n\nexport type SceneIlluminationUncertainty =\n | {\n kind: \"relative\";\n fraction: number;\n basis: string;\n }\n | {\n kind: \"not-quantified\";\n limitation: string;\n };\n\nexport type SceneIlluminationSourceGeometry =\n | {\n kind: \"point-position\";\n positionM: Vector3;\n }\n | {\n kind: \"scene-object-binding\";\n sceneObjectId: string;\n }\n | {\n kind: \"spot\";\n origin:\n | {\n kind: \"point-position\";\n positionM: Vector3;\n }\n | {\n kind: \"scene-object-binding\";\n sceneObjectId: string;\n };\n directionUnitVector: Vector3;\n outerConeAngleDegrees: number;\n }\n | {\n kind: \"directional\";\n directionUnitVector: Vector3;\n }\n | {\n kind: \"environment\";\n };\n\nexport type SceneIlluminationMagnitude =\n | {\n kind: \"relative-linear-scale\";\n scale: number;\n scientificStatus: \"approximation\";\n limitation: string;\n }\n | {\n kind: \"radiant-intensity\";\n wattsPerSteradian: number;\n scientificStatus: SceneIlluminationScientificStatus;\n uncertainty: SceneIlluminationUncertainty;\n evidence: readonly EvidenceProvenance[];\n }\n | {\n kind: \"surface-radiance\";\n wattsPerSquareMeterSteradian: number;\n scientificStatus: SceneIlluminationScientificStatus;\n uncertainty: SceneIlluminationUncertainty;\n evidence: readonly EvidenceProvenance[];\n }\n | {\n kind: \"reference-plane-irradiance\";\n wattsPerSquareMeter: number;\n referencePlaneId: string;\n scientificStatus: SceneIlluminationScientificStatus;\n uncertainty: SceneIlluminationUncertainty;\n evidence: readonly EvidenceProvenance[];\n };\n\nexport interface SceneIlluminationRelativeSpectrumSample {\n wavelengthNanometers: number;\n relativeDensityPerNanometer: number;\n}\n\nexport type SceneIlluminationSpectrum =\n | {\n kind: \"unresolved\";\n limitation: string;\n }\n | {\n kind: \"rgb-preview-approximation\";\n colorSpace: \"linear-srgb\";\n red: number;\n green: number;\n blue: number;\n limitation: string;\n }\n | {\n kind: \"blackbody-temperature-approximation\";\n temperatureKelvin: number;\n limitation: string;\n }\n | {\n kind: \"continuous-relative-spectrum\";\n spectrumId: string;\n wavelengthUnit: \"nm\";\n wavelengthBasis: SpectralWavelengthBasis;\n interpolation: \"piecewise-linear\";\n outsideRangeBehavior: \"fail-closed\";\n normalization: \"arbitrary-relative-scale\";\n scientificStatus:\n | \"calibrated-relative-shape\"\n | \"approximation\";\n uncertainty: SceneIlluminationUncertainty;\n evidence: readonly EvidenceProvenance[];\n samples:\n readonly SceneIlluminationRelativeSpectrumSample[];\n }\n | {\n kind: \"discrete-relative-lines\";\n spectrumId: string;\n wavelengthUnit: \"nm\";\n scientificStatus:\n | \"calibrated-relative-lines\"\n | \"approximation\";\n uncertainty: SceneIlluminationUncertainty;\n evidence: readonly EvidenceProvenance[];\n distribution:\n NormalizedDiscreteSpectralLineDistribution;\n };\n\nexport interface SceneIlluminationSource {\n sourceId: string;\n family: SceneIlluminationSourceFamily;\n enabled: boolean;\n geometry: SceneIlluminationSourceGeometry;\n magnitude: SceneIlluminationMagnitude;\n spectrum: SceneIlluminationSpectrum;\n temporalBehavior: {\n kind: \"time-invariant\";\n };\n evidence: readonly EvidenceProvenance[];\n limitations?: readonly string[];\n}\n\nexport interface SceneIlluminationProfile {\n schemaVersion:\n typeof SCENE_ILLUMINATION_PROFILE_SCHEMA_VERSION;\n profileId: string;\n sceneId: string;\n evidence: readonly EvidenceProvenance[];\n sources: readonly SceneIlluminationSource[];\n sceneRadianceCalculated: false;\n materialResponseApplied: false;\n visibilityEvaluated: false;\n indirectTransportEvaluated: false;\n fluorescenceModeled: false;\n volumetricTransportModeled: false;\n polarizationModeled: false;\n}\n\nfunction requireRecord(\n value: unknown,\n path: string,\n allowedKeys: readonly string[] | null\n): UnknownRecord {\n if (\n typeof value !== \"object\" ||\n value === null ||\n Array.isArray(value)\n ) {\n throw new InvalidConfigurationError(\n path + \" must be an object.\"\n );\n }\n if (allowedKeys !== null) rejectUnknownFields(value, allowedKeys, path);\n return value as UnknownRecord;\n}\n\nfunction requireNonEmptyString(\n value: unknown,\n path: string\n): string {\n if (\n typeof value !== \"string\" ||\n value.trim().length === 0\n ) {\n throw new InvalidConfigurationError(\n path + \" must be a non-empty string.\"\n );\n }\n return value.trim();\n}\n\nfunction requireBoolean(\n value: unknown,\n path: string\n): boolean {\n if (typeof value !== \"boolean\") {\n throw new InvalidConfigurationError(\n path + \" must be a boolean.\"\n );\n }\n return value;\n}\n\nfunction requireFinite(\n value: unknown,\n path: string\n): number {\n if (\n typeof value !== \"number\" ||\n !Number.isFinite(value)\n ) {\n throw new InvalidConfigurationError(\n path + \" must be a finite number.\"\n );\n }\n return value;\n}\n\nfunction requirePositiveFinite(\n value: unknown,\n path: string\n): number {\n const number = requireFinite(value, path);\n if (number <= 0) {\n throw new InvalidConfigurationError(\n path + \" must be greater than zero.\"\n );\n }\n return number;\n}\n\nfunction requireNonNegativeFinite(\n value: unknown,\n path: string\n): number {\n const number = requireFinite(value, path);\n if (number < 0) {\n throw new InvalidConfigurationError(\n path + \" must be greater than or equal to zero.\"\n );\n }\n return number;\n}\n\nfunction requireFraction(\n value: unknown,\n path: string\n): number {\n const number = requireFinite(value, path);\n if (number < 0 || number > 1) {\n throw new InvalidConfigurationError(\n path + \" must be a finite fraction from 0 through 1.\"\n );\n }\n return number;\n}\n\nfunction parseVector3(\n value: unknown,\n path: string\n): Vector3 {\n const record = requireRecord(value, path, [\"x\", \"y\", \"z\"]);\n return {\n x: requireFinite(record.x, path + \".x\"),\n y: requireFinite(record.y, path + \".y\"),\n z: requireFinite(record.z, path + \".z\")\n };\n}\n\nfunction parseDirectionUnitVector(\n value: unknown,\n path: string\n): Vector3 {\n const vector = parseVector3(value, path);\n const magnitude = Math.hypot(\n vector.x,\n vector.y,\n vector.z\n );\n if (\n !Number.isFinite(magnitude) ||\n Math.abs(magnitude - 1) > 1e-9\n ) {\n throw new InvalidConfigurationError(\n path + \" must be a unit-length direction vector.\"\n );\n }\n return vector;\n}\n\nfunction parseScientificStatus(\n value: unknown,\n path: string\n): SceneIlluminationScientificStatus {\n if (\n value !== \"calibrated\" &&\n value !== \"approximation\"\n ) {\n throw new InvalidConfigurationError(\n path + \" is invalid.\"\n );\n }\n return value;\n}\n\nfunction parseUncertainty(\n value: unknown,\n path: string\n): SceneIlluminationUncertainty {\n const record = requireRecord(value, path, null);\n\n if (record.kind === \"relative\") {\n rejectUnknownFields(record, [\"kind\", \"fraction\", \"basis\"], path);\n return {\n kind: \"relative\",\n fraction: requireNonNegativeFinite(\n record.fraction,\n path + \".fraction\"\n ),\n basis: requireNonEmptyString(\n record.basis,\n path + \".basis\"\n )\n };\n }\n\n if (record.kind === \"not-quantified\") {\n rejectUnknownFields(record, [\"kind\", \"limitation\"], path);\n return {\n kind: \"not-quantified\",\n limitation: requireNonEmptyString(\n record.limitation,\n path + \".limitation\"\n )\n };\n }\n\n throw new InvalidConfigurationError(\n path + \".kind is invalid.\"\n );\n}\n\nfunction validateCalibratedUncertainty(\n scientificStatus:\n SceneIlluminationScientificStatus,\n uncertainty: SceneIlluminationUncertainty,\n path: string\n): void {\n if (\n scientificStatus === \"calibrated\" &&\n uncertainty.kind !== \"relative\"\n ) {\n throw new InvalidConfigurationError(\n path +\n \" calibrated physical magnitude requires quantified relative uncertainty.\"\n );\n }\n}\n\nfunction parsePointOrigin(\n value: unknown,\n path: string\n):\n | {\n kind: \"point-position\";\n positionM: Vector3;\n }\n | {\n kind: \"scene-object-binding\";\n sceneObjectId: string;\n } {\n const record = requireRecord(value, path, null);\n\n if (record.kind === \"point-position\") {\n rejectUnknownFields(record, [\"kind\", \"positionM\"], path);\n return {\n kind: \"point-position\",\n positionM: parseVector3(\n record.positionM,\n path + \".positionM\"\n )\n };\n }\n\n if (record.kind === \"scene-object-binding\") {\n rejectUnknownFields(record, [\"kind\", \"sceneObjectId\"], path);\n return {\n kind: \"scene-object-binding\",\n sceneObjectId: requireNonEmptyString(\n record.sceneObjectId,\n path + \".sceneObjectId\"\n )\n };\n }\n\n throw new InvalidConfigurationError(\n path + \".kind is invalid.\"\n );\n}\n\nfunction parseGeometry(\n family: SceneIlluminationSourceFamily,\n value: unknown,\n path: string\n): SceneIlluminationSourceGeometry {\n // The allowed fields depend on the source family; parsePointOrigin checks the point geometry.\n const record = requireRecord(value, path, null);\n\n if (family === \"point\") {\n return parsePointOrigin(record, path);\n }\n\n if (family === \"spot\") {\n if (record.kind !== \"spot\") {\n throw new InvalidConfigurationError(\n path + '.kind must be \"spot\" for a spot source.'\n );\n }\n rejectUnknownFields(record, [\"kind\", \"origin\", \"directionUnitVector\", \"outerConeAngleDegrees\"], path);\n const outerConeAngleDegrees =\n requirePositiveFinite(\n record.outerConeAngleDegrees,\n path + \".outerConeAngleDegrees\"\n );\n if (outerConeAngleDegrees >= 180) {\n throw new InvalidConfigurationError(\n path +\n \".outerConeAngleDegrees must be less than 180.\"\n );\n }\n return {\n kind: \"spot\",\n origin: parsePointOrigin(\n record.origin,\n path + \".origin\"\n ),\n directionUnitVector:\n parseDirectionUnitVector(\n record.directionUnitVector,\n path + \".directionUnitVector\"\n ),\n outerConeAngleDegrees\n };\n }\n\n if (family === \"area\") {\n if (record.kind !== \"scene-object-binding\") {\n throw new InvalidConfigurationError(\n path +\n '.kind must be \"scene-object-binding\" for an area source so emitting geometry remains scene-owned.'\n );\n }\n rejectUnknownFields(record, [\"kind\", \"sceneObjectId\"], path);\n return {\n kind: \"scene-object-binding\",\n sceneObjectId: requireNonEmptyString(\n record.sceneObjectId,\n path + \".sceneObjectId\"\n )\n };\n }\n\n if (family === \"directional\") {\n if (record.kind !== \"directional\") {\n throw new InvalidConfigurationError(\n path +\n '.kind must be \"directional\" for a directional source.'\n );\n }\n rejectUnknownFields(record, [\"kind\", \"directionUnitVector\"], path);\n return {\n kind: \"directional\",\n directionUnitVector:\n parseDirectionUnitVector(\n record.directionUnitVector,\n path + \".directionUnitVector\"\n )\n };\n }\n\n if (record.kind !== \"environment\") {\n throw new InvalidConfigurationError(\n path +\n '.kind must be \"environment\" for an environment source.'\n );\n }\n rejectUnknownFields(record, [\"kind\"], path);\n return { kind: \"environment\" };\n}\n\nfunction parseMagnitude(\n family: SceneIlluminationSourceFamily,\n value: unknown,\n path: string\n): SceneIlluminationMagnitude {\n const record = requireRecord(value, path, null);\n rejectUnknownVariantFields(record, \"kind\", {\n \"relative-linear-scale\": [\"kind\", \"scale\", \"scientificStatus\", \"limitation\"],\n \"radiant-intensity\": [\"kind\", \"wattsPerSteradian\", \"scientificStatus\", \"uncertainty\", \"evidence\"],\n \"surface-radiance\": [\"kind\", \"wattsPerSquareMeterSteradian\", \"scientificStatus\", \"uncertainty\", \"evidence\"],\n \"reference-plane-irradiance\": [\"kind\", \"wattsPerSquareMeter\", \"referencePlaneId\", \"scientificStatus\", \"uncertainty\", \"evidence\"]\n }, path);\n\n if (record.kind === \"relative-linear-scale\") {\n if (record.scientificStatus !== \"approximation\") {\n throw new InvalidConfigurationError(\n path +\n '.scientificStatus must be \"approximation\" for relative-linear-scale.'\n );\n }\n return {\n kind: \"relative-linear-scale\",\n scale: requirePositiveFinite(\n record.scale,\n path + \".scale\"\n ),\n scientificStatus: \"approximation\",\n limitation: requireNonEmptyString(\n record.limitation,\n path + \".limitation\"\n )\n };\n }\n\n const scientificStatus =\n parseScientificStatus(\n record.scientificStatus,\n path + \".scientificStatus\"\n );\n const uncertainty =\n parseUncertainty(\n record.uncertainty,\n path + \".uncertainty\"\n );\n validateCalibratedUncertainty(\n scientificStatus,\n uncertainty,\n path\n );\n const evidence = parseEvidenceList(\n record.evidence,\n path + \".evidence\"\n );\n\n if (\n record.kind === \"radiant-intensity\" &&\n family === \"point\"\n ) {\n return {\n kind: \"radiant-intensity\",\n wattsPerSteradian:\n requirePositiveFinite(\n record.wattsPerSteradian,\n path + \".wattsPerSteradian\"\n ),\n scientificStatus,\n uncertainty,\n evidence\n };\n }\n\n if (\n record.kind === \"surface-radiance\" &&\n family === \"area\"\n ) {\n return {\n kind: \"surface-radiance\",\n wattsPerSquareMeterSteradian:\n requirePositiveFinite(\n record.wattsPerSquareMeterSteradian,\n path +\n \".wattsPerSquareMeterSteradian\"\n ),\n scientificStatus,\n uncertainty,\n evidence\n };\n }\n\n if (\n record.kind ===\n \"reference-plane-irradiance\" &&\n family === \"directional\"\n ) {\n return {\n kind: \"reference-plane-irradiance\",\n wattsPerSquareMeter:\n requirePositiveFinite(\n record.wattsPerSquareMeter,\n path + \".wattsPerSquareMeter\"\n ),\n referencePlaneId:\n requireNonEmptyString(\n record.referencePlaneId,\n path + \".referencePlaneId\"\n ),\n scientificStatus,\n uncertainty,\n evidence\n };\n }\n\n throw new InvalidConfigurationError(\n path +\n \".kind is not supported for source family \" +\n family +\n \".\"\n );\n}\n\nfunction requireReusableSpectrumEvidence(\n value: unknown,\n path: string\n): readonly EvidenceProvenance[] {\n const evidence = parseEvidenceList(\n value,\n path\n );\n if (\n !evidence.some(\n (entry) =>\n entry.reuseStatus ===\n \"reusable-data\" ||\n entry.reuseStatus ===\n \"photivra-owned\"\n )\n ) {\n throw new InvalidConfigurationError(\n path +\n \" must contain reusable-data or photivra-owned evidence because the spectrum embeds reusable numeric data.\"\n );\n }\n return evidence;\n}\n\nfunction parseSpectrum(\n value: unknown,\n path: string\n): SceneIlluminationSpectrum {\n const record = requireRecord(value, path, null);\n rejectUnknownVariantFields(record, \"kind\", {\n unresolved: [\"kind\", \"limitation\"],\n \"rgb-preview-approximation\": [\"kind\", \"colorSpace\", \"red\", \"green\", \"blue\", \"limitation\"],\n \"blackbody-temperature-approximation\": [\"kind\", \"temperatureKelvin\", \"limitation\"],\n \"discrete-relative-lines\": [\"kind\", \"spectrumId\", \"wavelengthUnit\", \"scientificStatus\", \"uncertainty\", \"evidence\", \"distribution\"],\n \"continuous-relative-spectrum\": [\"kind\", \"spectrumId\", \"wavelengthUnit\", \"wavelengthBasis\", \"interpolation\", \"outsideRangeBehavior\",\n \"normalization\", \"scientificStatus\", \"uncertainty\", \"evidence\", \"samples\"]\n }, path);\n\n if (record.kind === \"unresolved\") {\n return {\n kind: \"unresolved\",\n limitation: requireNonEmptyString(\n record.limitation,\n path + \".limitation\"\n )\n };\n }\n\n if (\n record.kind ===\n \"rgb-preview-approximation\"\n ) {\n if (record.colorSpace !== \"linear-srgb\") {\n throw new InvalidConfigurationError(\n path +\n '.colorSpace must be \"linear-srgb\" for the first RGB preview approximation.'\n );\n }\n return {\n kind: \"rgb-preview-approximation\",\n colorSpace: \"linear-srgb\",\n red: requireFraction(\n record.red,\n path + \".red\"\n ),\n green: requireFraction(\n record.green,\n path + \".green\"\n ),\n blue: requireFraction(\n record.blue,\n path + \".blue\"\n ),\n limitation: requireNonEmptyString(\n record.limitation,\n path + \".limitation\"\n )\n };\n }\n\n if (\n record.kind ===\n \"blackbody-temperature-approximation\"\n ) {\n return {\n kind: \"blackbody-temperature-approximation\",\n temperatureKelvin:\n requirePositiveFinite(\n record.temperatureKelvin,\n path + \".temperatureKelvin\"\n ),\n limitation: requireNonEmptyString(\n record.limitation,\n path + \".limitation\"\n )\n };\n }\n\n if (\n record.kind ===\n \"discrete-relative-lines\"\n ) {\n if (record.wavelengthUnit !== \"nm\") {\n throw new InvalidConfigurationError(\n path + '.wavelengthUnit must be \"nm\".'\n );\n }\n if (\n record.scientificStatus !==\n \"calibrated-relative-lines\" &&\n record.scientificStatus !==\n \"approximation\"\n ) {\n throw new InvalidConfigurationError(\n path + \".scientificStatus is invalid.\"\n );\n }\n const uncertainty =\n parseUncertainty(\n record.uncertainty,\n path + \".uncertainty\"\n );\n if (\n record.scientificStatus ===\n \"calibrated-relative-lines\" &&\n uncertainty.kind !== \"relative\"\n ) {\n throw new InvalidConfigurationError(\n path +\n \" calibrated-relative-lines spectra require quantified relative uncertainty.\"\n );\n }\n\n return {\n kind: \"discrete-relative-lines\",\n spectrumId: requireNonEmptyString(\n record.spectrumId,\n path + \".spectrumId\"\n ),\n wavelengthUnit: \"nm\",\n scientificStatus:\n record.scientificStatus,\n uncertainty,\n evidence:\n requireReusableSpectrumEvidence(\n record.evidence,\n path + \".evidence\"\n ),\n distribution:\n parseNormalizedDiscreteSpectralLineDistribution(\n record.distribution,\n path + \".distribution\"\n )\n };\n }\n\n if (\n record.kind !==\n \"continuous-relative-spectrum\"\n ) {\n throw new InvalidConfigurationError(\n path + \".kind is invalid.\"\n );\n }\n\n if (record.wavelengthUnit !== \"nm\") {\n throw new InvalidConfigurationError(\n path + '.wavelengthUnit must be \"nm\".'\n );\n }\n if (\n record.interpolation !==\n \"piecewise-linear\"\n ) {\n throw new InvalidConfigurationError(\n path +\n '.interpolation must be \"piecewise-linear\".'\n );\n }\n if (\n record.outsideRangeBehavior !==\n \"fail-closed\"\n ) {\n throw new InvalidConfigurationError(\n path +\n '.outsideRangeBehavior must be \"fail-closed\".'\n );\n }\n if (\n record.normalization !==\n \"arbitrary-relative-scale\"\n ) {\n throw new InvalidConfigurationError(\n path +\n '.normalization must be \"arbitrary-relative-scale\".'\n );\n }\n if (\n record.scientificStatus !==\n \"calibrated-relative-shape\" &&\n record.scientificStatus !==\n \"approximation\"\n ) {\n throw new InvalidConfigurationError(\n path + \".scientificStatus is invalid.\"\n );\n }\n\n const wavelengthBasis =\n parseSpectralWavelengthBasis(\n record.wavelengthBasis,\n path + \".wavelengthBasis\"\n );\n const uncertainty =\n parseUncertainty(\n record.uncertainty,\n path + \".uncertainty\"\n );\n if (\n record.scientificStatus ===\n \"calibrated-relative-shape\" &&\n wavelengthBasis === \"unspecified\"\n ) {\n throw new InvalidConfigurationError(\n path +\n ' calibrated-relative-shape spectra must declare wavelengthBasis \"air\" or \"vacuum\".'\n );\n }\n if (\n record.scientificStatus ===\n \"calibrated-relative-shape\" &&\n uncertainty.kind !== \"relative\"\n ) {\n throw new InvalidConfigurationError(\n path +\n \" calibrated-relative-shape spectra require quantified relative uncertainty.\"\n );\n }\n\n const evidence =\n requireReusableSpectrumEvidence(\n record.evidence,\n path + \".evidence\"\n );\n if (\n !Array.isArray(record.samples) ||\n record.samples.length < 2\n ) {\n throw new InvalidConfigurationError(\n path +\n \".samples must contain at least two wavelength samples.\"\n );\n }\n\n let previousWavelength =\n Number.NEGATIVE_INFINITY;\n let hasPositiveDensity = false;\n const samples = record.samples.map(\n (entry, index) => {\n const sample = requireRecord(\n entry,\n path + \".samples[\" + index + \"]\", [\"wavelengthNanometers\", \"relativeDensityPerNanometer\"]\n );\n const wavelengthNanometers =\n requirePositiveFinite(\n sample.wavelengthNanometers,\n path +\n \".samples[\" +\n index +\n \"].wavelengthNanometers\"\n );\n if (\n wavelengthNanometers <=\n previousWavelength\n ) {\n throw new InvalidConfigurationError(\n path +\n \".samples wavelengths must be strictly increasing.\"\n );\n }\n previousWavelength =\n wavelengthNanometers;\n const relativeDensityPerNanometer =\n requireNonNegativeFinite(\n sample.relativeDensityPerNanometer,\n path +\n \".samples[\" +\n index +\n \"].relativeDensityPerNanometer\"\n );\n if (relativeDensityPerNanometer > 0) {\n hasPositiveDensity = true;\n }\n return {\n wavelengthNanometers,\n relativeDensityPerNanometer\n };\n }\n );\n\n if (!hasPositiveDensity) {\n throw new InvalidConfigurationError(\n path +\n \".samples must contain at least one positive relative density.\"\n );\n }\n\n return {\n kind: \"continuous-relative-spectrum\",\n spectrumId: requireNonEmptyString(\n record.spectrumId,\n path + \".spectrumId\"\n ),\n wavelengthUnit: \"nm\",\n wavelengthBasis,\n interpolation: \"piecewise-linear\",\n outsideRangeBehavior: \"fail-closed\",\n normalization: \"arbitrary-relative-scale\",\n scientificStatus:\n record.scientificStatus,\n uncertainty,\n evidence,\n samples\n };\n}\n\nfunction parseLimitations(\n value: unknown,\n path: string\n): readonly string[] {\n if (!Array.isArray(value)) {\n throw new InvalidConfigurationError(\n path + \" must be an array.\"\n );\n }\n const limitations = value.map(\n (entry, index) =>\n requireNonEmptyString(\n entry,\n path + \"[\" + index + \"]\"\n )\n );\n if (\n new Set(limitations).size !==\n limitations.length\n ) {\n throw new InvalidConfigurationError(\n path + \" must not contain duplicates.\"\n );\n }\n return limitations;\n}\n\nfunction parseFamily(\n value: unknown,\n path: string\n): SceneIlluminationSourceFamily {\n if (\n value !== \"point\" &&\n value !== \"spot\" &&\n value !== \"area\" &&\n value !== \"directional\" &&\n value !== \"environment\"\n ) {\n throw new InvalidConfigurationError(\n path + \" is invalid.\"\n );\n }\n return value;\n}\n\n/** Parses one source of a scene illumination profile (also used by record-taking helpers). Not a root export. */\nexport function parseSceneIlluminationSource(\n value: unknown,\n path: string\n): SceneIlluminationSource {\n const record = requireRecord(value, path, [\"family\", \"temporalBehavior\", \"sourceId\", \"enabled\", \"geometry\", \"magnitude\", \"spectrum\", \"evidence\", \"limitations\"]);\n const family = parseFamily(\n record.family,\n path + \".family\"\n );\n\n const temporalBehavior =\n requireRecord(\n record.temporalBehavior,\n path + \".temporalBehavior\", [\"kind\"]\n );\n if (\n temporalBehavior.kind !==\n \"time-invariant\"\n ) {\n throw new InvalidConfigurationError(\n path +\n '.temporalBehavior.kind must be \"time-invariant\" in schema 0.1.0.'\n );\n }\n\n return {\n sourceId: requireNonEmptyString(\n record.sourceId,\n path + \".sourceId\"\n ),\n family,\n enabled: requireBoolean(\n record.enabled,\n path + \".enabled\"\n ),\n geometry: parseGeometry(\n family,\n record.geometry,\n path + \".geometry\"\n ),\n magnitude: parseMagnitude(\n family,\n record.magnitude,\n path + \".magnitude\"\n ),\n spectrum: parseSpectrum(\n record.spectrum,\n path + \".spectrum\"\n ),\n temporalBehavior: {\n kind: \"time-invariant\"\n },\n evidence: parseEvidenceList(\n record.evidence,\n path + \".evidence\"\n ),\n ...(record.limitations === undefined\n ? {}\n : {\n limitations: parseLimitations(\n record.limitations,\n path + \".limitations\"\n )\n })\n };\n}\n\n/** Fixed flags the parser writes; a parsed profile may carry them back in unchanged. */\nconst ILLUMINATION_PROFILE_FIXED_FIELDS = {\n sceneRadianceCalculated: false, materialResponseApplied: false, visibilityEvaluated: false,\n indirectTransportEvaluated: false, fluorescenceModeled: false, volumetricTransportModeled: false,\n polarizationModeled: false\n} as const;\n\n/**\n * Parses a renderer-independent scene illumination profile.\n *\n * The result describes light sources only. It does not compute outgoing scene\n * radiance, material response, visibility or indirect light, and on its own it\n * does not justify photon or electron counts downstream.\n */\nexport function parseSceneIlluminationProfile(\n value: unknown\n): SceneIlluminationProfile {\n const record = requireRecord(\n value,\n \"sceneIlluminationProfile\", [\"schemaVersion\", \"sources\", \"profileId\", \"sceneId\", \"evidence\", ...Object.keys(ILLUMINATION_PROFILE_FIXED_FIELDS)]\n );\n requireFixedFieldsWhenPresent(record, ILLUMINATION_PROFILE_FIXED_FIELDS, \"sceneIlluminationProfile\");\n\n if (\n record.schemaVersion !==\n SCENE_ILLUMINATION_PROFILE_SCHEMA_VERSION\n ) {\n throw new InvalidConfigurationError(\n 'sceneIlluminationProfile.schemaVersion must be \"' +\n SCENE_ILLUMINATION_PROFILE_SCHEMA_VERSION +\n '\".'\n );\n }\n\n if (!Array.isArray(record.sources)) {\n throw new InvalidConfigurationError(\n \"sceneIlluminationProfile.sources must be an array.\"\n );\n }\n\n const sources = record.sources.map(\n (source, index) =>\n parseSceneIlluminationSource(\n source,\n \"sceneIlluminationProfile.sources[\" +\n index +\n \"]\"\n )\n );\n const sourceIds = sources.map(\n (source) => source.sourceId\n );\n if (\n new Set(sourceIds).size !==\n sourceIds.length\n ) {\n throw new InvalidConfigurationError(\n \"sceneIlluminationProfile.sources[].sourceId must not contain duplicates.\"\n );\n }\n\n return {\n schemaVersion:\n SCENE_ILLUMINATION_PROFILE_SCHEMA_VERSION,\n profileId: requireNonEmptyString(\n record.profileId,\n \"sceneIlluminationProfile.profileId\"\n ),\n sceneId: requireNonEmptyString(\n record.sceneId,\n \"sceneIlluminationProfile.sceneId\"\n ),\n evidence: parseEvidenceList(\n record.evidence,\n \"sceneIlluminationProfile.evidence\"\n ),\n sources,\n sceneRadianceCalculated: false,\n materialResponseApplied: false,\n visibilityEvaluated: false,\n indirectTransportEvaluated: false,\n fluorescenceModeled: false,\n volumetricTransportModeled: false,\n polarizationModeled: false\n };\n}\n"]}
|
|
1
|
+
{"version":3,"file":"illumination.js","sourceRoot":"","sources":["../../src/schema/illumination.ts"],"names":[],"mappings":"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","sourcesContent":["// SPDX-License-Identifier: Apache-2.0\n\n/**\n * Scene illumination profiles: the light sources in a scene, independent of any renderer.\n *\n * A profile describes sources only. It does not compute the light leaving surfaces\n * (outgoing scene radiance), material response, visibility or indirect light, and on its\n * own it does not justify photon or electron counts downstream.\n * @see docs/SCENE_RADIANCE_AND_ILLUMINATION.md for equations, coordinate/unit conventions, blockers\n * and support limits.\n */\n\nimport { rejectUnknownFields, rejectUnknownVariantFields, requireFixedFieldsWhenPresent, requireConfigRecord as requireRecord, requireTrimmedConfigString as requireNonEmptyString, parseConfigScientificStatus as parseScientificStatus, requireConfigFiniteNumber as requireFinite, parseConfigLimitations as parseLimitations, requireConfigFraction as requireFraction, requireConfigNumberAtLeastZero as requireNonNegativeFinite, requireConfigNumberAboveZero as requirePositiveFinite } from \"../core/record-validation.js\";\nimport { InvalidConfigurationError } from \"../core/configuration-error.js\";\nimport {\n parseEvidenceList,\n type EvidenceProvenance\n} from \"../core/evidence-provenance.js\";\nimport {\n parseSpectralWavelengthBasis,\n type SpectralWavelengthBasis\n} from \"../core/spectral.js\";\nimport {\n parseNormalizedDiscreteSpectralLineDistribution,\n type NormalizedDiscreteSpectralLineDistribution\n} from \"../core/spectral-composition.js\";\nimport type { Vector3 } from \"./scene.js\";\n\nexport const SCENE_ILLUMINATION_PROFILE_SCHEMA_VERSION = \"0.1.0\" as const;\n\nexport type SceneIlluminationSourceFamily =\n | \"point\"\n | \"spot\"\n | \"area\"\n | \"directional\"\n | \"environment\";\n\nexport type SceneIlluminationScientificStatus =\n | \"calibrated\"\n | \"approximation\";\n\nexport type SceneIlluminationUncertainty =\n | {\n kind: \"relative\";\n fraction: number;\n basis: string;\n }\n | {\n kind: \"not-quantified\";\n limitation: string;\n };\n\nexport type SceneIlluminationSourceGeometry =\n | {\n kind: \"point-position\";\n positionM: Vector3;\n }\n | {\n kind: \"scene-object-binding\";\n sceneObjectId: string;\n }\n | {\n kind: \"spot\";\n origin:\n | {\n kind: \"point-position\";\n positionM: Vector3;\n }\n | {\n kind: \"scene-object-binding\";\n sceneObjectId: string;\n };\n directionUnitVector: Vector3;\n outerConeAngleDegrees: number;\n }\n | {\n kind: \"directional\";\n directionUnitVector: Vector3;\n }\n | {\n kind: \"environment\";\n };\n\nexport type SceneIlluminationMagnitude =\n | {\n kind: \"relative-linear-scale\";\n scale: number;\n scientificStatus: \"approximation\";\n limitation: string;\n }\n | {\n kind: \"radiant-intensity\";\n wattsPerSteradian: number;\n scientificStatus: SceneIlluminationScientificStatus;\n uncertainty: SceneIlluminationUncertainty;\n evidence: readonly EvidenceProvenance[];\n }\n | {\n kind: \"surface-radiance\";\n wattsPerSquareMeterSteradian: number;\n scientificStatus: SceneIlluminationScientificStatus;\n uncertainty: SceneIlluminationUncertainty;\n evidence: readonly EvidenceProvenance[];\n }\n | {\n kind: \"reference-plane-irradiance\";\n wattsPerSquareMeter: number;\n referencePlaneId: string;\n scientificStatus: SceneIlluminationScientificStatus;\n uncertainty: SceneIlluminationUncertainty;\n evidence: readonly EvidenceProvenance[];\n };\n\nexport interface SceneIlluminationRelativeSpectrumSample {\n wavelengthNanometers: number;\n relativeDensityPerNanometer: number;\n}\n\nexport type SceneIlluminationSpectrum =\n | {\n kind: \"unresolved\";\n limitation: string;\n }\n | {\n kind: \"rgb-preview-approximation\";\n colorSpace: \"linear-srgb\";\n red: number;\n green: number;\n blue: number;\n limitation: string;\n }\n | {\n kind: \"blackbody-temperature-approximation\";\n temperatureKelvin: number;\n limitation: string;\n }\n | {\n kind: \"continuous-relative-spectrum\";\n spectrumId: string;\n wavelengthUnit: \"nm\";\n wavelengthBasis: SpectralWavelengthBasis;\n interpolation: \"piecewise-linear\";\n outsideRangeBehavior: \"fail-closed\";\n normalization: \"arbitrary-relative-scale\";\n scientificStatus:\n | \"calibrated-relative-shape\"\n | \"approximation\";\n uncertainty: SceneIlluminationUncertainty;\n evidence: readonly EvidenceProvenance[];\n samples:\n readonly SceneIlluminationRelativeSpectrumSample[];\n }\n | {\n kind: \"discrete-relative-lines\";\n spectrumId: string;\n wavelengthUnit: \"nm\";\n scientificStatus:\n | \"calibrated-relative-lines\"\n | \"approximation\";\n uncertainty: SceneIlluminationUncertainty;\n evidence: readonly EvidenceProvenance[];\n distribution:\n NormalizedDiscreteSpectralLineDistribution;\n };\n\nexport interface SceneIlluminationSource {\n sourceId: string;\n family: SceneIlluminationSourceFamily;\n enabled: boolean;\n geometry: SceneIlluminationSourceGeometry;\n magnitude: SceneIlluminationMagnitude;\n spectrum: SceneIlluminationSpectrum;\n temporalBehavior: {\n kind: \"time-invariant\";\n };\n evidence: readonly EvidenceProvenance[];\n limitations?: readonly string[];\n}\n\nexport interface SceneIlluminationProfile {\n schemaVersion:\n typeof SCENE_ILLUMINATION_PROFILE_SCHEMA_VERSION;\n profileId: string;\n sceneId: string;\n evidence: readonly EvidenceProvenance[];\n sources: readonly SceneIlluminationSource[];\n sceneRadianceCalculated: false;\n materialResponseApplied: false;\n visibilityEvaluated: false;\n indirectTransportEvaluated: false;\n fluorescenceModeled: false;\n volumetricTransportModeled: false;\n polarizationModeled: false;\n}\n\nfunction requireBoolean(\n value: unknown,\n path: string\n): boolean {\n if (typeof value !== \"boolean\") {\n throw new InvalidConfigurationError(\n path + \" must be a boolean.\"\n );\n }\n return value;\n}\n\nexport function parseVector3(\n value: unknown,\n path: string\n): Vector3 {\n const record = requireRecord(value, path, [\"x\", \"y\", \"z\"]);\n return {\n x: requireFinite(record.x, path + \".x\"),\n y: requireFinite(record.y, path + \".y\"),\n z: requireFinite(record.z, path + \".z\")\n };\n}\n\nfunction parseDirectionUnitVector(\n value: unknown,\n path: string\n): Vector3 {\n const vector = parseVector3(value, path);\n const magnitude = Math.hypot(\n vector.x,\n vector.y,\n vector.z\n );\n if (\n !Number.isFinite(magnitude) ||\n Math.abs(magnitude - 1) > 1e-9\n ) {\n throw new InvalidConfigurationError(\n path + \" must be a unit-length direction vector.\"\n );\n }\n return vector;\n}\n\nfunction parseUncertainty(\n value: unknown,\n path: string\n): SceneIlluminationUncertainty {\n const record = requireRecord(value, path, null);\n\n if (record.kind === \"relative\") {\n rejectUnknownFields(record, [\"kind\", \"fraction\", \"basis\"], path);\n return {\n kind: \"relative\",\n fraction: requireNonNegativeFinite(\n record.fraction,\n path + \".fraction\"\n ),\n basis: requireNonEmptyString(\n record.basis,\n path + \".basis\"\n )\n };\n }\n\n if (record.kind === \"not-quantified\") {\n rejectUnknownFields(record, [\"kind\", \"limitation\"], path);\n return {\n kind: \"not-quantified\",\n limitation: requireNonEmptyString(\n record.limitation,\n path + \".limitation\"\n )\n };\n }\n\n throw new InvalidConfigurationError(\n path + \".kind is invalid.\"\n );\n}\n\nfunction validateCalibratedUncertainty(\n scientificStatus:\n SceneIlluminationScientificStatus,\n uncertainty: SceneIlluminationUncertainty,\n path: string\n): void {\n if (\n scientificStatus === \"calibrated\" &&\n uncertainty.kind !== \"relative\"\n ) {\n throw new InvalidConfigurationError(\n path +\n \" calibrated physical magnitude requires quantified relative uncertainty.\"\n );\n }\n}\n\nfunction parsePointOrigin(\n value: unknown,\n path: string\n):\n | {\n kind: \"point-position\";\n positionM: Vector3;\n }\n | {\n kind: \"scene-object-binding\";\n sceneObjectId: string;\n } {\n const record = requireRecord(value, path, null);\n\n if (record.kind === \"point-position\") {\n rejectUnknownFields(record, [\"kind\", \"positionM\"], path);\n return {\n kind: \"point-position\",\n positionM: parseVector3(\n record.positionM,\n path + \".positionM\"\n )\n };\n }\n\n if (record.kind === \"scene-object-binding\") {\n rejectUnknownFields(record, [\"kind\", \"sceneObjectId\"], path);\n return {\n kind: \"scene-object-binding\",\n sceneObjectId: requireNonEmptyString(\n record.sceneObjectId,\n path + \".sceneObjectId\"\n )\n };\n }\n\n throw new InvalidConfigurationError(\n path + \".kind is invalid.\"\n );\n}\n\nfunction parseGeometry(\n family: SceneIlluminationSourceFamily,\n value: unknown,\n path: string\n): SceneIlluminationSourceGeometry {\n // The allowed fields depend on the source family; parsePointOrigin checks the point geometry.\n const record = requireRecord(value, path, null);\n\n if (family === \"point\") {\n return parsePointOrigin(record, path);\n }\n\n if (family === \"spot\") {\n if (record.kind !== \"spot\") {\n throw new InvalidConfigurationError(\n path + '.kind must be \"spot\" for a spot source.'\n );\n }\n rejectUnknownFields(record, [\"kind\", \"origin\", \"directionUnitVector\", \"outerConeAngleDegrees\"], path);\n const outerConeAngleDegrees =\n requirePositiveFinite(\n record.outerConeAngleDegrees,\n path + \".outerConeAngleDegrees\"\n );\n if (outerConeAngleDegrees >= 180) {\n throw new InvalidConfigurationError(\n path +\n \".outerConeAngleDegrees must be less than 180.\"\n );\n }\n return {\n kind: \"spot\",\n origin: parsePointOrigin(\n record.origin,\n path + \".origin\"\n ),\n directionUnitVector:\n parseDirectionUnitVector(\n record.directionUnitVector,\n path + \".directionUnitVector\"\n ),\n outerConeAngleDegrees\n };\n }\n\n if (family === \"area\") {\n if (record.kind !== \"scene-object-binding\") {\n throw new InvalidConfigurationError(\n path +\n '.kind must be \"scene-object-binding\" for an area source so emitting geometry remains scene-owned.'\n );\n }\n rejectUnknownFields(record, [\"kind\", \"sceneObjectId\"], path);\n return {\n kind: \"scene-object-binding\",\n sceneObjectId: requireNonEmptyString(\n record.sceneObjectId,\n path + \".sceneObjectId\"\n )\n };\n }\n\n if (family === \"directional\") {\n if (record.kind !== \"directional\") {\n throw new InvalidConfigurationError(\n path +\n '.kind must be \"directional\" for a directional source.'\n );\n }\n rejectUnknownFields(record, [\"kind\", \"directionUnitVector\"], path);\n return {\n kind: \"directional\",\n directionUnitVector:\n parseDirectionUnitVector(\n record.directionUnitVector,\n path + \".directionUnitVector\"\n )\n };\n }\n\n if (record.kind !== \"environment\") {\n throw new InvalidConfigurationError(\n path +\n '.kind must be \"environment\" for an environment source.'\n );\n }\n rejectUnknownFields(record, [\"kind\"], path);\n return { kind: \"environment\" };\n}\n\nfunction parseMagnitude(\n family: SceneIlluminationSourceFamily,\n value: unknown,\n path: string\n): SceneIlluminationMagnitude {\n const record = requireRecord(value, path, null);\n rejectUnknownVariantFields(record, \"kind\", {\n \"relative-linear-scale\": [\"kind\", \"scale\", \"scientificStatus\", \"limitation\"],\n \"radiant-intensity\": [\"kind\", \"wattsPerSteradian\", \"scientificStatus\", \"uncertainty\", \"evidence\"],\n \"surface-radiance\": [\"kind\", \"wattsPerSquareMeterSteradian\", \"scientificStatus\", \"uncertainty\", \"evidence\"],\n \"reference-plane-irradiance\": [\"kind\", \"wattsPerSquareMeter\", \"referencePlaneId\", \"scientificStatus\", \"uncertainty\", \"evidence\"]\n }, path);\n\n if (record.kind === \"relative-linear-scale\") {\n if (record.scientificStatus !== \"approximation\") {\n throw new InvalidConfigurationError(\n path +\n '.scientificStatus must be \"approximation\" for relative-linear-scale.'\n );\n }\n return {\n kind: \"relative-linear-scale\",\n scale: requirePositiveFinite(\n record.scale,\n path + \".scale\"\n ),\n scientificStatus: \"approximation\",\n limitation: requireNonEmptyString(\n record.limitation,\n path + \".limitation\"\n )\n };\n }\n\n const scientificStatus =\n parseScientificStatus(\n record.scientificStatus,\n path + \".scientificStatus\"\n );\n const uncertainty =\n parseUncertainty(\n record.uncertainty,\n path + \".uncertainty\"\n );\n validateCalibratedUncertainty(\n scientificStatus,\n uncertainty,\n path\n );\n const evidence = parseEvidenceList(\n record.evidence,\n path + \".evidence\"\n );\n\n if (\n record.kind === \"radiant-intensity\" &&\n family === \"point\"\n ) {\n return {\n kind: \"radiant-intensity\",\n wattsPerSteradian:\n requirePositiveFinite(\n record.wattsPerSteradian,\n path + \".wattsPerSteradian\"\n ),\n scientificStatus,\n uncertainty,\n evidence\n };\n }\n\n if (\n record.kind === \"surface-radiance\" &&\n family === \"area\"\n ) {\n return {\n kind: \"surface-radiance\",\n wattsPerSquareMeterSteradian:\n requirePositiveFinite(\n record.wattsPerSquareMeterSteradian,\n path +\n \".wattsPerSquareMeterSteradian\"\n ),\n scientificStatus,\n uncertainty,\n evidence\n };\n }\n\n if (\n record.kind ===\n \"reference-plane-irradiance\" &&\n family === \"directional\"\n ) {\n return {\n kind: \"reference-plane-irradiance\",\n wattsPerSquareMeter:\n requirePositiveFinite(\n record.wattsPerSquareMeter,\n path + \".wattsPerSquareMeter\"\n ),\n referencePlaneId:\n requireNonEmptyString(\n record.referencePlaneId,\n path + \".referencePlaneId\"\n ),\n scientificStatus,\n uncertainty,\n evidence\n };\n }\n\n throw new InvalidConfigurationError(\n path +\n \".kind is not supported for source family \" +\n family +\n \".\"\n );\n}\n\nfunction requireReusableSpectrumEvidence(\n value: unknown,\n path: string\n): readonly EvidenceProvenance[] {\n const evidence = parseEvidenceList(\n value,\n path\n );\n if (\n !evidence.some(\n (entry) =>\n entry.reuseStatus ===\n \"reusable-data\" ||\n entry.reuseStatus ===\n \"photivra-owned\"\n )\n ) {\n throw new InvalidConfigurationError(\n path +\n \" must contain reusable-data or photivra-owned evidence because the spectrum embeds reusable numeric data.\"\n );\n }\n return evidence;\n}\n\nfunction parseSpectrum(\n value: unknown,\n path: string\n): SceneIlluminationSpectrum {\n const record = requireRecord(value, path, null);\n rejectUnknownVariantFields(record, \"kind\", {\n unresolved: [\"kind\", \"limitation\"],\n \"rgb-preview-approximation\": [\"kind\", \"colorSpace\", \"red\", \"green\", \"blue\", \"limitation\"],\n \"blackbody-temperature-approximation\": [\"kind\", \"temperatureKelvin\", \"limitation\"],\n \"discrete-relative-lines\": [\"kind\", \"spectrumId\", \"wavelengthUnit\", \"scientificStatus\", \"uncertainty\", \"evidence\", \"distribution\"],\n \"continuous-relative-spectrum\": [\"kind\", \"spectrumId\", \"wavelengthUnit\", \"wavelengthBasis\", \"interpolation\", \"outsideRangeBehavior\",\n \"normalization\", \"scientificStatus\", \"uncertainty\", \"evidence\", \"samples\"]\n }, path);\n\n if (record.kind === \"unresolved\") {\n return {\n kind: \"unresolved\",\n limitation: requireNonEmptyString(\n record.limitation,\n path + \".limitation\"\n )\n };\n }\n\n if (\n record.kind ===\n \"rgb-preview-approximation\"\n ) {\n if (record.colorSpace !== \"linear-srgb\") {\n throw new InvalidConfigurationError(\n path +\n '.colorSpace must be \"linear-srgb\" for the first RGB preview approximation.'\n );\n }\n return {\n kind: \"rgb-preview-approximation\",\n colorSpace: \"linear-srgb\",\n red: requireFraction(\n record.red,\n path + \".red\"\n ),\n green: requireFraction(\n record.green,\n path + \".green\"\n ),\n blue: requireFraction(\n record.blue,\n path + \".blue\"\n ),\n limitation: requireNonEmptyString(\n record.limitation,\n path + \".limitation\"\n )\n };\n }\n\n if (\n record.kind ===\n \"blackbody-temperature-approximation\"\n ) {\n return {\n kind: \"blackbody-temperature-approximation\",\n temperatureKelvin:\n requirePositiveFinite(\n record.temperatureKelvin,\n path + \".temperatureKelvin\"\n ),\n limitation: requireNonEmptyString(\n record.limitation,\n path + \".limitation\"\n )\n };\n }\n\n if (\n record.kind ===\n \"discrete-relative-lines\"\n ) {\n if (record.wavelengthUnit !== \"nm\") {\n throw new InvalidConfigurationError(\n path + '.wavelengthUnit must be \"nm\".'\n );\n }\n if (\n record.scientificStatus !==\n \"calibrated-relative-lines\" &&\n record.scientificStatus !==\n \"approximation\"\n ) {\n throw new InvalidConfigurationError(\n path + \".scientificStatus is invalid.\"\n );\n }\n const uncertainty =\n parseUncertainty(\n record.uncertainty,\n path + \".uncertainty\"\n );\n if (\n record.scientificStatus ===\n \"calibrated-relative-lines\" &&\n uncertainty.kind !== \"relative\"\n ) {\n throw new InvalidConfigurationError(\n path +\n \" calibrated-relative-lines spectra require quantified relative uncertainty.\"\n );\n }\n\n return {\n kind: \"discrete-relative-lines\",\n spectrumId: requireNonEmptyString(\n record.spectrumId,\n path + \".spectrumId\"\n ),\n wavelengthUnit: \"nm\",\n scientificStatus:\n record.scientificStatus,\n uncertainty,\n evidence:\n requireReusableSpectrumEvidence(\n record.evidence,\n path + \".evidence\"\n ),\n distribution:\n parseNormalizedDiscreteSpectralLineDistribution(\n record.distribution,\n path + \".distribution\"\n )\n };\n }\n\n if (\n record.kind !==\n \"continuous-relative-spectrum\"\n ) {\n throw new InvalidConfigurationError(\n path + \".kind is invalid.\"\n );\n }\n\n if (record.wavelengthUnit !== \"nm\") {\n throw new InvalidConfigurationError(\n path + '.wavelengthUnit must be \"nm\".'\n );\n }\n if (\n record.interpolation !==\n \"piecewise-linear\"\n ) {\n throw new InvalidConfigurationError(\n path +\n '.interpolation must be \"piecewise-linear\".'\n );\n }\n if (\n record.outsideRangeBehavior !==\n \"fail-closed\"\n ) {\n throw new InvalidConfigurationError(\n path +\n '.outsideRangeBehavior must be \"fail-closed\".'\n );\n }\n if (\n record.normalization !==\n \"arbitrary-relative-scale\"\n ) {\n throw new InvalidConfigurationError(\n path +\n '.normalization must be \"arbitrary-relative-scale\".'\n );\n }\n if (\n record.scientificStatus !==\n \"calibrated-relative-shape\" &&\n record.scientificStatus !==\n \"approximation\"\n ) {\n throw new InvalidConfigurationError(\n path + \".scientificStatus is invalid.\"\n );\n }\n\n const wavelengthBasis =\n parseSpectralWavelengthBasis(\n record.wavelengthBasis,\n path + \".wavelengthBasis\"\n );\n const uncertainty =\n parseUncertainty(\n record.uncertainty,\n path + \".uncertainty\"\n );\n if (\n record.scientificStatus ===\n \"calibrated-relative-shape\" &&\n wavelengthBasis === \"unspecified\"\n ) {\n throw new InvalidConfigurationError(\n path +\n ' calibrated-relative-shape spectra must declare wavelengthBasis \"air\" or \"vacuum\".'\n );\n }\n if (\n record.scientificStatus ===\n \"calibrated-relative-shape\" &&\n uncertainty.kind !== \"relative\"\n ) {\n throw new InvalidConfigurationError(\n path +\n \" calibrated-relative-shape spectra require quantified relative uncertainty.\"\n );\n }\n\n const evidence =\n requireReusableSpectrumEvidence(\n record.evidence,\n path + \".evidence\"\n );\n if (\n !Array.isArray(record.samples) ||\n record.samples.length < 2\n ) {\n throw new InvalidConfigurationError(\n path +\n \".samples must contain at least two wavelength samples.\"\n );\n }\n\n let previousWavelength =\n Number.NEGATIVE_INFINITY;\n let hasPositiveDensity = false;\n const samples = record.samples.map(\n (entry, index) => {\n const sample = requireRecord(\n entry,\n path + \".samples[\" + index + \"]\", [\"wavelengthNanometers\", \"relativeDensityPerNanometer\"]\n );\n const wavelengthNanometers =\n requirePositiveFinite(\n sample.wavelengthNanometers,\n path +\n \".samples[\" +\n index +\n \"].wavelengthNanometers\"\n );\n if (\n wavelengthNanometers <=\n previousWavelength\n ) {\n throw new InvalidConfigurationError(\n path +\n \".samples wavelengths must be strictly increasing.\"\n );\n }\n previousWavelength =\n wavelengthNanometers;\n const relativeDensityPerNanometer =\n requireNonNegativeFinite(\n sample.relativeDensityPerNanometer,\n path +\n \".samples[\" +\n index +\n \"].relativeDensityPerNanometer\"\n );\n if (relativeDensityPerNanometer > 0) {\n hasPositiveDensity = true;\n }\n return {\n wavelengthNanometers,\n relativeDensityPerNanometer\n };\n }\n );\n\n if (!hasPositiveDensity) {\n throw new InvalidConfigurationError(\n path +\n \".samples must contain at least one positive relative density.\"\n );\n }\n\n return {\n kind: \"continuous-relative-spectrum\",\n spectrumId: requireNonEmptyString(\n record.spectrumId,\n path + \".spectrumId\"\n ),\n wavelengthUnit: \"nm\",\n wavelengthBasis,\n interpolation: \"piecewise-linear\",\n outsideRangeBehavior: \"fail-closed\",\n normalization: \"arbitrary-relative-scale\",\n scientificStatus:\n record.scientificStatus,\n uncertainty,\n evidence,\n samples\n };\n}\n\nfunction parseFamily(\n value: unknown,\n path: string\n): SceneIlluminationSourceFamily {\n if (\n value !== \"point\" &&\n value !== \"spot\" &&\n value !== \"area\" &&\n value !== \"directional\" &&\n value !== \"environment\"\n ) {\n throw new InvalidConfigurationError(\n path + \" is invalid.\"\n );\n }\n return value;\n}\n\n/** Parses one source of a scene illumination profile (also used by record-taking helpers). Not a root export. */\nexport function parseSceneIlluminationSource(\n value: unknown,\n path: string\n): SceneIlluminationSource {\n const record = requireRecord(value, path, [\"family\", \"temporalBehavior\", \"sourceId\", \"enabled\", \"geometry\", \"magnitude\", \"spectrum\", \"evidence\", \"limitations\"]);\n const family = parseFamily(\n record.family,\n path + \".family\"\n );\n\n const temporalBehavior =\n requireRecord(\n record.temporalBehavior,\n path + \".temporalBehavior\", [\"kind\"]\n );\n if (\n temporalBehavior.kind !==\n \"time-invariant\"\n ) {\n throw new InvalidConfigurationError(\n path +\n '.temporalBehavior.kind must be \"time-invariant\" in schema 0.1.0.'\n );\n }\n\n return {\n sourceId: requireNonEmptyString(\n record.sourceId,\n path + \".sourceId\"\n ),\n family,\n enabled: requireBoolean(\n record.enabled,\n path + \".enabled\"\n ),\n geometry: parseGeometry(\n family,\n record.geometry,\n path + \".geometry\"\n ),\n magnitude: parseMagnitude(\n family,\n record.magnitude,\n path + \".magnitude\"\n ),\n spectrum: parseSpectrum(\n record.spectrum,\n path + \".spectrum\"\n ),\n temporalBehavior: {\n kind: \"time-invariant\"\n },\n evidence: parseEvidenceList(\n record.evidence,\n path + \".evidence\"\n ),\n ...(record.limitations === undefined\n ? {}\n : {\n limitations: parseLimitations(\n record.limitations,\n path + \".limitations\"\n )\n })\n };\n}\n\n/** Fixed flags the parser writes; a parsed profile may carry them back in unchanged. */\nconst ILLUMINATION_PROFILE_FIXED_FIELDS = {\n sceneRadianceCalculated: false, materialResponseApplied: false, visibilityEvaluated: false,\n indirectTransportEvaluated: false, fluorescenceModeled: false, volumetricTransportModeled: false,\n polarizationModeled: false\n} as const;\n\n/**\n * Parses a renderer-independent scene illumination profile.\n *\n * The result describes light sources only. It does not compute outgoing scene\n * radiance, material response, visibility or indirect light, and on its own it\n * does not justify photon or electron counts downstream.\n */\nexport function parseSceneIlluminationProfile(\n value: unknown\n): SceneIlluminationProfile {\n const record = requireRecord(\n value,\n \"sceneIlluminationProfile\", [\"schemaVersion\", \"sources\", \"profileId\", \"sceneId\", \"evidence\", ...Object.keys(ILLUMINATION_PROFILE_FIXED_FIELDS)]\n );\n requireFixedFieldsWhenPresent(record, ILLUMINATION_PROFILE_FIXED_FIELDS, \"sceneIlluminationProfile\");\n\n if (\n record.schemaVersion !==\n SCENE_ILLUMINATION_PROFILE_SCHEMA_VERSION\n ) {\n throw new InvalidConfigurationError(\n 'sceneIlluminationProfile.schemaVersion must be \"' +\n SCENE_ILLUMINATION_PROFILE_SCHEMA_VERSION +\n '\".'\n );\n }\n\n if (!Array.isArray(record.sources)) {\n throw new InvalidConfigurationError(\n \"sceneIlluminationProfile.sources must be an array.\"\n );\n }\n\n const sources = record.sources.map(\n (source, index) =>\n parseSceneIlluminationSource(\n source,\n \"sceneIlluminationProfile.sources[\" +\n index +\n \"]\"\n )\n );\n const sourceIds = sources.map(\n (source) => source.sourceId\n );\n if (\n new Set(sourceIds).size !==\n sourceIds.length\n ) {\n throw new InvalidConfigurationError(\n \"sceneIlluminationProfile.sources[].sourceId must not contain duplicates.\"\n );\n }\n\n return {\n schemaVersion:\n SCENE_ILLUMINATION_PROFILE_SCHEMA_VERSION,\n profileId: requireNonEmptyString(\n record.profileId,\n \"sceneIlluminationProfile.profileId\"\n ),\n sceneId: requireNonEmptyString(\n record.sceneId,\n \"sceneIlluminationProfile.sceneId\"\n ),\n evidence: parseEvidenceList(\n record.evidence,\n \"sceneIlluminationProfile.evidence\"\n ),\n sources,\n sceneRadianceCalculated: false,\n materialResponseApplied: false,\n visibilityEvaluated: false,\n indirectTransportEvaluated: false,\n fluorescenceModeled: false,\n volumetricTransportModeled: false,\n polarizationModeled: false\n };\n}\n"]}
|
|
@@ -14,21 +14,9 @@
|
|
|
14
14
|
*/
|
|
15
15
|
import { InvalidScientificInputError, requirePositiveInteger } from "../core/validation.js";
|
|
16
16
|
import { parseSceneRadianceEvaluationRequest, parseSceneRadianceEvaluationResult } from "./scene-radiance.js";
|
|
17
|
-
import { requireInputKeys } from "../core/record-validation.js";
|
|
18
|
-
import {
|
|
17
|
+
import { requireInputKeys, requireTrimmedConfigString as requireNonEmptyString } from "../core/record-validation.js";
|
|
18
|
+
import { sameSite as samePoint } from "../core/shared-helpers.js";
|
|
19
19
|
export const SCENE_RADIANCE_TEMPORAL_SAMPLING_PLAN_VERSION = "0.1.0";
|
|
20
|
-
function requireNonEmptyString(value, path) {
|
|
21
|
-
if (typeof value !== "string" ||
|
|
22
|
-
value.trim().length === 0) {
|
|
23
|
-
throw new InvalidConfigurationError(path +
|
|
24
|
-
" must be a non-empty string.");
|
|
25
|
-
}
|
|
26
|
-
return value.trim();
|
|
27
|
-
}
|
|
28
|
-
function samePoint(a, b) {
|
|
29
|
-
return (a.x === b.x &&
|
|
30
|
-
a.y === b.y);
|
|
31
|
-
}
|
|
32
20
|
function exposureForPoint(timing, point) {
|
|
33
21
|
const matches = timing.exposureWindows.samples.filter((sample) => samePoint(sample.pointNative, point));
|
|
34
22
|
if (matches.length !== 1) {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"scene-radiance-temporal.js","sourceRoot":"","sources":["../../src/schema/scene-radiance-temporal.ts"],"names":[],"mappings":"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","sourcesContent":["// SPDX-License-Identifier: Apache-2.0\n\n/**\n * Scene radiance over an exposure window, in two steps.\n *\n * 1. Plan: list the times (nodes) at which a scene-radiance provider (a renderer or other\n * source of scene light) must report radiance during one local exposure window.\n * 2. Reduce: combine the provider's per-wavelength results over that window.\n *\n * Each returned sample must match its planned node, time and result identity exactly.\n * Uncertainty stays per node and is not combined, because no correlation or independence\n * is assumed.\n * @see docs/SCENE_RADIANCE_AND_ILLUMINATION.md for equations, coordinate/unit conventions, blockers\n * and support limits.\n */\n\nimport { InvalidScientificInputError, requirePositiveInteger } from \"../core/validation.js\";\nimport type { RasterPoint } from \"../output/capture-geometry.js\";\nimport {\n parseSceneRadianceEvaluationRequest,\n parseSceneRadianceEvaluationResult,\n type SceneRadianceEvaluationRequest,\n type SceneRadianceEvaluationResult\n} from \"./scene-radiance.js\";\nimport type {\n ResolvedCaptureModeTiming\n} from \"../sensor/capture-mode-timing.js\";\nimport { requireInputKeys } from \"../core/record-validation.js\";\nimport { InvalidConfigurationError } from \"../core/configuration-error.js\";\n\nexport const SCENE_RADIANCE_TEMPORAL_SAMPLING_PLAN_VERSION =\n \"0.1.0\" as const;\n\nexport interface SceneRadianceTemporalQuery {\n providerProfileId: string;\n sceneId: string;\n illuminationProfileId: string;\n materialResponseProfileId: string;\n target:\n SceneRadianceEvaluationRequest[\"target\"];\n wavelengthNanometers: number;\n wavelengthBasis:\n SceneRadianceEvaluationRequest[\"wavelengthBasis\"];\n}\n\nexport interface CreateSceneRadianceTemporalSamplingPlanInput {\n planId: string;\n timing:\n ResolvedCaptureModeTiming;\n destinationPointNative:\n RasterPoint;\n temporalSampleCount: number;\n query:\n SceneRadianceTemporalQuery;\n}\n\nexport interface SceneRadianceTemporalSamplingNode {\n nodeId: string;\n expectedResultSampleId: string;\n temporalSampleIndex: number;\n localExposurePhase: number;\n captureTimeSecondsFromReference:\n number;\n normalizedTimeWeight: number;\n timeMeasureSeconds: number;\n}\n\nexport interface SceneRadianceTemporalSamplingPlan {\n version:\n typeof SCENE_RADIANCE_TEMPORAL_SAMPLING_PLAN_VERSION;\n planId: string;\n timeReference:\n \"first-opening-boundary-phase\";\n timingProfileIdentity: {\n profileId: string;\n profileVersion: string;\n captureModeId: string;\n };\n destinationPointNative:\n RasterPoint;\n localExposureWindow: {\n startSecondsFromCaptureReference:\n number;\n endSecondsFromCaptureReference:\n number;\n durationSeconds: number;\n };\n temporalSampleCount: number;\n quadratureScheme:\n \"uniform-midpoint\";\n query:\n SceneRadianceTemporalQuery;\n nodes:\n readonly SceneRadianceTemporalSamplingNode[];\n providerMustEvaluateAtNodeCaptureTime:\n true;\n sensorReadoutTimingUsedAsExposureTiming:\n false;\n}\n\nexport interface SceneRadianceTemporalEvaluatedSample {\n nodeId: string;\n captureTimeSecondsFromReference:\n number;\n result:\n SceneRadianceEvaluationResult;\n}\n\nexport interface ReduceSceneRadianceTemporalSamplesInput {\n plan:\n SceneRadianceTemporalSamplingPlan;\n samples:\n readonly SceneRadianceTemporalEvaluatedSample[];\n}\n\nexport interface ReducedSceneRadianceTemporalExposure {\n version:\n typeof SCENE_RADIANCE_TEMPORAL_SAMPLING_PLAN_VERSION;\n planId: string;\n timeReference:\n \"first-opening-boundary-phase\";\n localExposureWindow:\n SceneRadianceTemporalSamplingPlan[\"localExposureWindow\"];\n temporalSampleCount: number;\n quadratureScheme:\n \"uniform-midpoint\";\n providerProfileId: string;\n sceneId: string;\n wavelengthNanometers: number;\n wavelengthBasis:\n SceneRadianceEvaluationRequest[\"wavelengthBasis\"];\n quantity:\n \"outgoing-spectral-radiance\";\n averageSpectralRadianceWattsPerSquareMeterSteradianNanometer:\n number;\n integratedSpectralRadianceWattSecondsPerSquareMeterSteradianNanometer:\n number;\n nodes: readonly {\n nodeId: string;\n captureTimeSecondsFromReference:\n number;\n normalizedTimeWeight: number;\n timeMeasureSeconds: number;\n spectralRadianceWattsPerSquareMeterSteradianNanometer:\n number;\n evidence:\n SceneRadianceEvaluationResult[\"evidence\"];\n uncertainty:\n SceneRadianceEvaluationResult[\"uncertainty\"];\n }[];\n scientificStatus: \"approximation\";\n uncertaintyPropagation:\n \"not-propagated\";\n uncertaintyLimitation: string;\n sensorReadoutTimingUsedAsExposureTiming:\n false;\n}\n\nfunction requireNonEmptyString(\n value: string,\n path: string\n): string {\n if (\n typeof value !== \"string\" ||\n value.trim().length === 0\n ) {\n throw new InvalidConfigurationError(\n path +\n \" must be a non-empty string.\"\n );\n }\n return value.trim();\n}\n\nfunction samePoint(\n a: RasterPoint,\n b: RasterPoint\n): boolean {\n return (\n a.x === b.x &&\n a.y === b.y\n );\n}\n\nfunction exposureForPoint(\n timing:\n ResolvedCaptureModeTiming,\n point:\n RasterPoint\n): ResolvedCaptureModeTiming[\"exposureWindows\"][\"samples\"][number] {\n const matches =\n timing.exposureWindows.samples.filter(\n (sample) =>\n samePoint(\n sample.pointNative,\n point\n )\n );\n if (matches.length !== 1) {\n throw new InvalidScientificInputError(\n \"destinationPointNative must match exactly one committed exposure-window sample.\"\n );\n }\n return matches[0]!;\n}\n\nfunction parseQuery(\n query:\n SceneRadianceTemporalQuery\n): SceneRadianceTemporalQuery {\n // Reuse the scene-radiance request parser for the shared scene and spectral\n // checks. The placeholder time it needs is not copied into the returned\n // temporal query, where it would be misleading.\n const parsed =\n parseSceneRadianceEvaluationRequest({\n schemaVersion: \"0.1.0\",\n sampleId:\n \"temporal-query-validation\",\n providerProfileId:\n query.providerProfileId,\n sceneId:\n query.sceneId,\n illuminationProfileId:\n query.illuminationProfileId,\n materialResponseProfileId:\n query.materialResponseProfileId,\n target:\n query.target,\n timeSecondsFromExposureStart:\n 0,\n wavelengthNanometers:\n query.wavelengthNanometers,\n wavelengthBasis:\n query.wavelengthBasis\n });\n\n return {\n providerProfileId:\n parsed.providerProfileId,\n sceneId:\n parsed.sceneId,\n illuminationProfileId:\n parsed.illuminationProfileId,\n materialResponseProfileId:\n parsed.materialResponseProfileId,\n target:\n parsed.target,\n wavelengthNanometers:\n parsed.wavelengthNanometers,\n wavelengthBasis:\n parsed.wavelengthBasis\n };\n}\n\n/**\n * Plans the times (nodes) at which a scene-radiance provider must report radiance\n * during one local exposure window. Works with any renderer or provider.\n *\n * Capture time is a separate field, not the older request field\n * timeSecondsFromExposureStart. Providers must evaluate radiance at\n * node.captureTimeSecondsFromReference, measured from the first opening boundary.\n */\nexport function createSceneRadianceTemporalSamplingPlan(\n input:\n CreateSceneRadianceTemporalSamplingPlanInput\n): SceneRadianceTemporalSamplingPlan {\n requireInputKeys(input, \"createSceneRadianceTemporalSamplingPlan\", [\"planId\", \"timing\", \"destinationPointNative\", \"temporalSampleCount\", \"query\"]);\n requirePositiveInteger(\n \"temporalSampleCount\",\n input.temporalSampleCount\n );\n const planId =\n requireNonEmptyString(\n input.planId,\n \"planId\"\n );\n const query =\n parseQuery(input.query);\n const exposure =\n exposureForPoint(\n input.timing,\n input\n .destinationPointNative\n );\n const duration =\n exposure\n .localExposureDurationSeconds;\n\n if (\n !Number.isFinite(duration) ||\n duration <= 0\n ) {\n throw new InvalidScientificInputError(\n \"Scene-radiance temporal sampling requires a positive finite local exposure duration.\"\n );\n }\n\n const normalizedTimeWeight =\n 1 /\n input.temporalSampleCount;\n const timeMeasureSeconds =\n duration /\n input.temporalSampleCount;\n\n const nodes =\n Array.from(\n {\n length:\n input.temporalSampleCount\n },\n (\n _,\n temporalSampleIndex\n ) => {\n const localExposurePhase =\n (temporalSampleIndex +\n 0.5) /\n input.temporalSampleCount;\n const captureTime =\n exposure\n .startOffsetSecondsFromOpeningReference +\n localExposurePhase *\n duration;\n return {\n nodeId:\n planId +\n \":node:\" +\n temporalSampleIndex,\n expectedResultSampleId:\n planId +\n \":radiance:\" +\n temporalSampleIndex,\n temporalSampleIndex,\n localExposurePhase,\n captureTimeSecondsFromReference:\n captureTime,\n normalizedTimeWeight,\n timeMeasureSeconds\n };\n }\n );\n\n return {\n version:\n SCENE_RADIANCE_TEMPORAL_SAMPLING_PLAN_VERSION,\n planId,\n timeReference:\n \"first-opening-boundary-phase\",\n timingProfileIdentity: {\n profileId:\n input.timing\n .timingProfileId,\n profileVersion:\n input.timing\n .timingProfileVersion,\n captureModeId:\n input.timing\n .captureModeId\n },\n destinationPointNative: {\n ...input\n .destinationPointNative\n },\n localExposureWindow: {\n startSecondsFromCaptureReference:\n exposure\n .startOffsetSecondsFromOpeningReference,\n endSecondsFromCaptureReference:\n exposure\n .endOffsetSecondsFromOpeningReference,\n durationSeconds:\n duration\n },\n temporalSampleCount:\n input.temporalSampleCount,\n quadratureScheme:\n \"uniform-midpoint\",\n query,\n nodes,\n providerMustEvaluateAtNodeCaptureTime:\n true,\n sensorReadoutTimingUsedAsExposureTiming:\n false\n };\n}\n\nfunction sameTime(\n a: number,\n b: number\n): boolean {\n const scale =\n Math.max(\n 1,\n Math.abs(a),\n Math.abs(b)\n );\n return (\n Math.abs(a - b) <=\n Number.EPSILON *\n 16 *\n scale\n );\n}\n\n/**\n * Combines the provider's per-wavelength scene radiance over the local exposure window.\n *\n * Each sample must match its planned node, time and result identity exactly.\n * Uncertainty stays per node and is not combined, because no correlation or\n * independence is assumed.\n */\nexport function reduceSceneRadianceTemporalSamples(\n input:\n ReduceSceneRadianceTemporalSamplesInput\n): ReducedSceneRadianceTemporalExposure {\n requireInputKeys(input, \"reduceSceneRadianceTemporalSamples\", [\"plan\", \"samples\"]);\n if (\n !Array.isArray(\n input.samples\n ) ||\n input.samples.length !==\n input.plan.nodes.length\n ) {\n throw new InvalidScientificInputError(\n \"samples must contain exactly one result for every temporal sampling node.\"\n );\n }\n\n const byNode =\n new Map(\n input.samples.map(\n (sample) => [\n sample.nodeId,\n sample\n ] as const\n )\n );\n if (\n byNode.size !==\n input.samples.length\n ) {\n throw new InvalidScientificInputError(\n \"samples must not contain duplicate nodeId values.\"\n );\n }\n\n let average = 0;\n let integrated = 0;\n\n const nodes =\n input.plan.nodes.map(\n (node) => {\n const supplied =\n byNode.get(\n node.nodeId\n );\n if (supplied === undefined) {\n throw new InvalidScientificInputError(\n \"A temporal scene-radiance node result is missing.\"\n );\n }\n if (\n !Number.isFinite(\n supplied\n .captureTimeSecondsFromReference\n ) ||\n !sameTime(\n supplied\n .captureTimeSecondsFromReference,\n node\n .captureTimeSecondsFromReference\n )\n ) {\n throw new InvalidScientificInputError(\n \"Temporal scene-radiance sample time must match its authoritative plan node.\"\n );\n }\n\n const result =\n parseSceneRadianceEvaluationResult(\n supplied.result\n );\n if (\n result.sampleId !==\n node.expectedResultSampleId ||\n result.providerProfileId !==\n input.plan.query\n .providerProfileId ||\n result.sceneId !==\n input.plan.query\n .sceneId ||\n result.wavelengthNanometers !==\n input.plan.query\n .wavelengthNanometers ||\n result.wavelengthBasis !==\n input.plan.query\n .wavelengthBasis\n ) {\n throw new InvalidScientificInputError(\n \"Temporal scene-radiance result identity must match the plan node/query exactly.\"\n );\n }\n\n const value =\n result\n .spectralRadianceWattsPerSquareMeterSteradianNanometer;\n average +=\n value *\n node\n .normalizedTimeWeight;\n integrated +=\n value *\n node\n .timeMeasureSeconds;\n\n return {\n nodeId:\n node.nodeId,\n captureTimeSecondsFromReference:\n node\n .captureTimeSecondsFromReference,\n normalizedTimeWeight:\n node\n .normalizedTimeWeight,\n timeMeasureSeconds:\n node\n .timeMeasureSeconds,\n spectralRadianceWattsPerSquareMeterSteradianNanometer:\n value,\n evidence:\n result.evidence,\n uncertainty:\n result.uncertainty\n };\n }\n );\n\n if (\n !Number.isFinite(average) ||\n average < 0 ||\n !Number.isFinite(\n integrated\n ) ||\n integrated < 0\n ) {\n throw new InvalidScientificInputError(\n \"Reduced temporal scene radiance must remain finite and non-negative.\"\n );\n }\n\n return {\n version:\n SCENE_RADIANCE_TEMPORAL_SAMPLING_PLAN_VERSION,\n planId:\n input.plan.planId,\n timeReference:\n \"first-opening-boundary-phase\",\n localExposureWindow: {\n ...input.plan\n .localExposureWindow\n },\n temporalSampleCount:\n input.plan\n .temporalSampleCount,\n quadratureScheme:\n \"uniform-midpoint\",\n providerProfileId:\n input.plan.query\n .providerProfileId,\n sceneId:\n input.plan.query.sceneId,\n wavelengthNanometers:\n input.plan.query\n .wavelengthNanometers,\n wavelengthBasis:\n input.plan.query\n .wavelengthBasis,\n quantity:\n \"outgoing-spectral-radiance\",\n averageSpectralRadianceWattsPerSquareMeterSteradianNanometer:\n average,\n integratedSpectralRadianceWattSecondsPerSquareMeterSteradianNanometer:\n integrated,\n nodes,\n scientificStatus:\n \"approximation\",\n uncertaintyPropagation:\n \"not-propagated\",\n uncertaintyLimitation:\n \"Per-node scene-radiance uncertainty is preserved; aggregate numeric uncertainty is not propagated because temporal correlation is not assumed.\",\n sensorReadoutTimingUsedAsExposureTiming:\n false\n };\n}\n"]}
|
|
1
|
+
{"version":3,"file":"scene-radiance-temporal.js","sourceRoot":"","sources":["../../src/schema/scene-radiance-temporal.ts"],"names":[],"mappings":"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","sourcesContent":["// SPDX-License-Identifier: Apache-2.0\n\n/**\n * Scene radiance over an exposure window, in two steps.\n *\n * 1. Plan: list the times (nodes) at which a scene-radiance provider (a renderer or other\n * source of scene light) must report radiance during one local exposure window.\n * 2. Reduce: combine the provider's per-wavelength results over that window.\n *\n * Each returned sample must match its planned node, time and result identity exactly.\n * Uncertainty stays per node and is not combined, because no correlation or independence\n * is assumed.\n * @see docs/SCENE_RADIANCE_AND_ILLUMINATION.md for equations, coordinate/unit conventions, blockers\n * and support limits.\n */\n\nimport { InvalidScientificInputError, requirePositiveInteger } from \"../core/validation.js\";\nimport type { RasterPoint } from \"../output/capture-geometry.js\";\nimport {\n parseSceneRadianceEvaluationRequest,\n parseSceneRadianceEvaluationResult,\n type SceneRadianceEvaluationRequest,\n type SceneRadianceEvaluationResult\n} from \"./scene-radiance.js\";\nimport type {\n ResolvedCaptureModeTiming\n} from \"../sensor/capture-mode-timing.js\";\nimport { requireInputKeys, requireTrimmedConfigString as requireNonEmptyString } from \"../core/record-validation.js\";\nimport { sameSite as samePoint } from \"../core/shared-helpers.js\";\n\nexport const SCENE_RADIANCE_TEMPORAL_SAMPLING_PLAN_VERSION =\n \"0.1.0\" as const;\n\nexport interface SceneRadianceTemporalQuery {\n providerProfileId: string;\n sceneId: string;\n illuminationProfileId: string;\n materialResponseProfileId: string;\n target:\n SceneRadianceEvaluationRequest[\"target\"];\n wavelengthNanometers: number;\n wavelengthBasis:\n SceneRadianceEvaluationRequest[\"wavelengthBasis\"];\n}\n\nexport interface CreateSceneRadianceTemporalSamplingPlanInput {\n planId: string;\n timing:\n ResolvedCaptureModeTiming;\n destinationPointNative:\n RasterPoint;\n temporalSampleCount: number;\n query:\n SceneRadianceTemporalQuery;\n}\n\nexport interface SceneRadianceTemporalSamplingNode {\n nodeId: string;\n expectedResultSampleId: string;\n temporalSampleIndex: number;\n localExposurePhase: number;\n captureTimeSecondsFromReference:\n number;\n normalizedTimeWeight: number;\n timeMeasureSeconds: number;\n}\n\nexport interface SceneRadianceTemporalSamplingPlan {\n version:\n typeof SCENE_RADIANCE_TEMPORAL_SAMPLING_PLAN_VERSION;\n planId: string;\n timeReference:\n \"first-opening-boundary-phase\";\n timingProfileIdentity: {\n profileId: string;\n profileVersion: string;\n captureModeId: string;\n };\n destinationPointNative:\n RasterPoint;\n localExposureWindow: {\n startSecondsFromCaptureReference:\n number;\n endSecondsFromCaptureReference:\n number;\n durationSeconds: number;\n };\n temporalSampleCount: number;\n quadratureScheme:\n \"uniform-midpoint\";\n query:\n SceneRadianceTemporalQuery;\n nodes:\n readonly SceneRadianceTemporalSamplingNode[];\n providerMustEvaluateAtNodeCaptureTime:\n true;\n sensorReadoutTimingUsedAsExposureTiming:\n false;\n}\n\nexport interface SceneRadianceTemporalEvaluatedSample {\n nodeId: string;\n captureTimeSecondsFromReference:\n number;\n result:\n SceneRadianceEvaluationResult;\n}\n\nexport interface ReduceSceneRadianceTemporalSamplesInput {\n plan:\n SceneRadianceTemporalSamplingPlan;\n samples:\n readonly SceneRadianceTemporalEvaluatedSample[];\n}\n\nexport interface ReducedSceneRadianceTemporalExposure {\n version:\n typeof SCENE_RADIANCE_TEMPORAL_SAMPLING_PLAN_VERSION;\n planId: string;\n timeReference:\n \"first-opening-boundary-phase\";\n localExposureWindow:\n SceneRadianceTemporalSamplingPlan[\"localExposureWindow\"];\n temporalSampleCount: number;\n quadratureScheme:\n \"uniform-midpoint\";\n providerProfileId: string;\n sceneId: string;\n wavelengthNanometers: number;\n wavelengthBasis:\n SceneRadianceEvaluationRequest[\"wavelengthBasis\"];\n quantity:\n \"outgoing-spectral-radiance\";\n averageSpectralRadianceWattsPerSquareMeterSteradianNanometer:\n number;\n integratedSpectralRadianceWattSecondsPerSquareMeterSteradianNanometer:\n number;\n nodes: readonly {\n nodeId: string;\n captureTimeSecondsFromReference:\n number;\n normalizedTimeWeight: number;\n timeMeasureSeconds: number;\n spectralRadianceWattsPerSquareMeterSteradianNanometer:\n number;\n evidence:\n SceneRadianceEvaluationResult[\"evidence\"];\n uncertainty:\n SceneRadianceEvaluationResult[\"uncertainty\"];\n }[];\n scientificStatus: \"approximation\";\n uncertaintyPropagation:\n \"not-propagated\";\n uncertaintyLimitation: string;\n sensorReadoutTimingUsedAsExposureTiming:\n false;\n}\n\nfunction exposureForPoint(\n timing:\n ResolvedCaptureModeTiming,\n point:\n RasterPoint\n): ResolvedCaptureModeTiming[\"exposureWindows\"][\"samples\"][number] {\n const matches =\n timing.exposureWindows.samples.filter(\n (sample) =>\n samePoint(\n sample.pointNative,\n point\n )\n );\n if (matches.length !== 1) {\n throw new InvalidScientificInputError(\n \"destinationPointNative must match exactly one committed exposure-window sample.\"\n );\n }\n return matches[0]!;\n}\n\nfunction parseQuery(\n query:\n SceneRadianceTemporalQuery\n): SceneRadianceTemporalQuery {\n // Reuse the scene-radiance request parser for the shared scene and spectral\n // checks. The placeholder time it needs is not copied into the returned\n // temporal query, where it would be misleading.\n const parsed =\n parseSceneRadianceEvaluationRequest({\n schemaVersion: \"0.1.0\",\n sampleId:\n \"temporal-query-validation\",\n providerProfileId:\n query.providerProfileId,\n sceneId:\n query.sceneId,\n illuminationProfileId:\n query.illuminationProfileId,\n materialResponseProfileId:\n query.materialResponseProfileId,\n target:\n query.target,\n timeSecondsFromExposureStart:\n 0,\n wavelengthNanometers:\n query.wavelengthNanometers,\n wavelengthBasis:\n query.wavelengthBasis\n });\n\n return {\n providerProfileId:\n parsed.providerProfileId,\n sceneId:\n parsed.sceneId,\n illuminationProfileId:\n parsed.illuminationProfileId,\n materialResponseProfileId:\n parsed.materialResponseProfileId,\n target:\n parsed.target,\n wavelengthNanometers:\n parsed.wavelengthNanometers,\n wavelengthBasis:\n parsed.wavelengthBasis\n };\n}\n\n/**\n * Plans the times (nodes) at which a scene-radiance provider must report radiance\n * during one local exposure window. Works with any renderer or provider.\n *\n * Capture time is a separate field, not the older request field\n * timeSecondsFromExposureStart. Providers must evaluate radiance at\n * node.captureTimeSecondsFromReference, measured from the first opening boundary.\n */\nexport function createSceneRadianceTemporalSamplingPlan(\n input:\n CreateSceneRadianceTemporalSamplingPlanInput\n): SceneRadianceTemporalSamplingPlan {\n requireInputKeys(input, \"createSceneRadianceTemporalSamplingPlan\", [\"planId\", \"timing\", \"destinationPointNative\", \"temporalSampleCount\", \"query\"]);\n requirePositiveInteger(\n \"temporalSampleCount\",\n input.temporalSampleCount\n );\n const planId =\n requireNonEmptyString(\n input.planId,\n \"planId\"\n );\n const query =\n parseQuery(input.query);\n const exposure =\n exposureForPoint(\n input.timing,\n input\n .destinationPointNative\n );\n const duration =\n exposure\n .localExposureDurationSeconds;\n\n if (\n !Number.isFinite(duration) ||\n duration <= 0\n ) {\n throw new InvalidScientificInputError(\n \"Scene-radiance temporal sampling requires a positive finite local exposure duration.\"\n );\n }\n\n const normalizedTimeWeight =\n 1 /\n input.temporalSampleCount;\n const timeMeasureSeconds =\n duration /\n input.temporalSampleCount;\n\n const nodes =\n Array.from(\n {\n length:\n input.temporalSampleCount\n },\n (\n _,\n temporalSampleIndex\n ) => {\n const localExposurePhase =\n (temporalSampleIndex +\n 0.5) /\n input.temporalSampleCount;\n const captureTime =\n exposure\n .startOffsetSecondsFromOpeningReference +\n localExposurePhase *\n duration;\n return {\n nodeId:\n planId +\n \":node:\" +\n temporalSampleIndex,\n expectedResultSampleId:\n planId +\n \":radiance:\" +\n temporalSampleIndex,\n temporalSampleIndex,\n localExposurePhase,\n captureTimeSecondsFromReference:\n captureTime,\n normalizedTimeWeight,\n timeMeasureSeconds\n };\n }\n );\n\n return {\n version:\n SCENE_RADIANCE_TEMPORAL_SAMPLING_PLAN_VERSION,\n planId,\n timeReference:\n \"first-opening-boundary-phase\",\n timingProfileIdentity: {\n profileId:\n input.timing\n .timingProfileId,\n profileVersion:\n input.timing\n .timingProfileVersion,\n captureModeId:\n input.timing\n .captureModeId\n },\n destinationPointNative: {\n ...input\n .destinationPointNative\n },\n localExposureWindow: {\n startSecondsFromCaptureReference:\n exposure\n .startOffsetSecondsFromOpeningReference,\n endSecondsFromCaptureReference:\n exposure\n .endOffsetSecondsFromOpeningReference,\n durationSeconds:\n duration\n },\n temporalSampleCount:\n input.temporalSampleCount,\n quadratureScheme:\n \"uniform-midpoint\",\n query,\n nodes,\n providerMustEvaluateAtNodeCaptureTime:\n true,\n sensorReadoutTimingUsedAsExposureTiming:\n false\n };\n}\n\nfunction sameTime(\n a: number,\n b: number\n): boolean {\n const scale =\n Math.max(\n 1,\n Math.abs(a),\n Math.abs(b)\n );\n return (\n Math.abs(a - b) <=\n Number.EPSILON *\n 16 *\n scale\n );\n}\n\n/**\n * Combines the provider's per-wavelength scene radiance over the local exposure window.\n *\n * Each sample must match its planned node, time and result identity exactly.\n * Uncertainty stays per node and is not combined, because no correlation or\n * independence is assumed.\n */\nexport function reduceSceneRadianceTemporalSamples(\n input:\n ReduceSceneRadianceTemporalSamplesInput\n): ReducedSceneRadianceTemporalExposure {\n requireInputKeys(input, \"reduceSceneRadianceTemporalSamples\", [\"plan\", \"samples\"]);\n if (\n !Array.isArray(\n input.samples\n ) ||\n input.samples.length !==\n input.plan.nodes.length\n ) {\n throw new InvalidScientificInputError(\n \"samples must contain exactly one result for every temporal sampling node.\"\n );\n }\n\n const byNode =\n new Map(\n input.samples.map(\n (sample) => [\n sample.nodeId,\n sample\n ] as const\n )\n );\n if (\n byNode.size !==\n input.samples.length\n ) {\n throw new InvalidScientificInputError(\n \"samples must not contain duplicate nodeId values.\"\n );\n }\n\n let average = 0;\n let integrated = 0;\n\n const nodes =\n input.plan.nodes.map(\n (node) => {\n const supplied =\n byNode.get(\n node.nodeId\n );\n if (supplied === undefined) {\n throw new InvalidScientificInputError(\n \"A temporal scene-radiance node result is missing.\"\n );\n }\n if (\n !Number.isFinite(\n supplied\n .captureTimeSecondsFromReference\n ) ||\n !sameTime(\n supplied\n .captureTimeSecondsFromReference,\n node\n .captureTimeSecondsFromReference\n )\n ) {\n throw new InvalidScientificInputError(\n \"Temporal scene-radiance sample time must match its authoritative plan node.\"\n );\n }\n\n const result =\n parseSceneRadianceEvaluationResult(\n supplied.result\n );\n if (\n result.sampleId !==\n node.expectedResultSampleId ||\n result.providerProfileId !==\n input.plan.query\n .providerProfileId ||\n result.sceneId !==\n input.plan.query\n .sceneId ||\n result.wavelengthNanometers !==\n input.plan.query\n .wavelengthNanometers ||\n result.wavelengthBasis !==\n input.plan.query\n .wavelengthBasis\n ) {\n throw new InvalidScientificInputError(\n \"Temporal scene-radiance result identity must match the plan node/query exactly.\"\n );\n }\n\n const value =\n result\n .spectralRadianceWattsPerSquareMeterSteradianNanometer;\n average +=\n value *\n node\n .normalizedTimeWeight;\n integrated +=\n value *\n node\n .timeMeasureSeconds;\n\n return {\n nodeId:\n node.nodeId,\n captureTimeSecondsFromReference:\n node\n .captureTimeSecondsFromReference,\n normalizedTimeWeight:\n node\n .normalizedTimeWeight,\n timeMeasureSeconds:\n node\n .timeMeasureSeconds,\n spectralRadianceWattsPerSquareMeterSteradianNanometer:\n value,\n evidence:\n result.evidence,\n uncertainty:\n result.uncertainty\n };\n }\n );\n\n if (\n !Number.isFinite(average) ||\n average < 0 ||\n !Number.isFinite(\n integrated\n ) ||\n integrated < 0\n ) {\n throw new InvalidScientificInputError(\n \"Reduced temporal scene radiance must remain finite and non-negative.\"\n );\n }\n\n return {\n version:\n SCENE_RADIANCE_TEMPORAL_SAMPLING_PLAN_VERSION,\n planId:\n input.plan.planId,\n timeReference:\n \"first-opening-boundary-phase\",\n localExposureWindow: {\n ...input.plan\n .localExposureWindow\n },\n temporalSampleCount:\n input.plan\n .temporalSampleCount,\n quadratureScheme:\n \"uniform-midpoint\",\n providerProfileId:\n input.plan.query\n .providerProfileId,\n sceneId:\n input.plan.query.sceneId,\n wavelengthNanometers:\n input.plan.query\n .wavelengthNanometers,\n wavelengthBasis:\n input.plan.query\n .wavelengthBasis,\n quantity:\n \"outgoing-spectral-radiance\",\n averageSpectralRadianceWattsPerSquareMeterSteradianNanometer:\n average,\n integratedSpectralRadianceWattSecondsPerSquareMeterSteradianNanometer:\n integrated,\n nodes,\n scientificStatus:\n \"approximation\",\n uncertaintyPropagation:\n \"not-propagated\",\n uncertaintyLimitation:\n \"Per-node scene-radiance uncertainty is preserved; aggregate numeric uncertainty is not propagated because temporal correlation is not assumed.\",\n sensorReadoutTimingUsedAsExposureTiming:\n false\n };\n}\n"]}
|
|
@@ -12,59 +12,12 @@
|
|
|
12
12
|
import { InvalidConfigurationError } from "../core/configuration-error.js";
|
|
13
13
|
import { parseEvidenceList } from "../core/evidence-provenance.js";
|
|
14
14
|
import { parseSpectralWavelengthBasis, parseSpectralWavelengthRangeNanometers } from "../core/spectral.js";
|
|
15
|
-
import { requireInputObject, requireInputArray, requireInputKeys,
|
|
15
|
+
import { requireInputObject, requireInputArray, requireInputKeys, rejectUnknownVariantFields, UNCERTAINTY_VARIANT_FIELDS, requireConfigRecord as requireRecord, requireTrimmedConfigString as requireNonEmptyString, requireConfigFiniteNumber as requireFinite, parseConfigLimitations as parseLimitations, requireConfigFraction as requireFraction, requireConfigNumberAtLeastZero as requireNonNegativeFinite } from "../core/record-validation.js";
|
|
16
16
|
import { hypot3 } from "../core/portable-math.js";
|
|
17
|
+
import { parseVector3 } from "./illumination.js";
|
|
17
18
|
export const SCENE_MATERIAL_RESPONSE_PROFILE_SCHEMA_VERSION = "0.1.0";
|
|
18
19
|
export const SCENE_RADIANCE_PROVIDER_PROFILE_SCHEMA_VERSION = "0.1.0";
|
|
19
20
|
export const SCENE_RADIANCE_EVALUATION_SCHEMA_VERSION = "0.1.0";
|
|
20
|
-
function requireRecord(value, path, allowedKeys) {
|
|
21
|
-
if (typeof value !== "object" ||
|
|
22
|
-
value === null ||
|
|
23
|
-
Array.isArray(value)) {
|
|
24
|
-
throw new InvalidConfigurationError(path + " must be an object.");
|
|
25
|
-
}
|
|
26
|
-
if (allowedKeys !== null)
|
|
27
|
-
rejectUnknownFields(value, allowedKeys, path);
|
|
28
|
-
return value;
|
|
29
|
-
}
|
|
30
|
-
function requireNonEmptyString(value, path) {
|
|
31
|
-
if (typeof value !== "string" ||
|
|
32
|
-
value.trim().length === 0) {
|
|
33
|
-
throw new InvalidConfigurationError(path + " must be a non-empty string.");
|
|
34
|
-
}
|
|
35
|
-
return value.trim();
|
|
36
|
-
}
|
|
37
|
-
function requireFinite(value, path) {
|
|
38
|
-
if (typeof value !== "number" ||
|
|
39
|
-
!Number.isFinite(value)) {
|
|
40
|
-
throw new InvalidConfigurationError(path + " must be a finite number.");
|
|
41
|
-
}
|
|
42
|
-
return value;
|
|
43
|
-
}
|
|
44
|
-
function requireNonNegativeFinite(value, path) {
|
|
45
|
-
const number = requireFinite(value, path);
|
|
46
|
-
if (number < 0) {
|
|
47
|
-
throw new InvalidConfigurationError(path +
|
|
48
|
-
" must be greater than or equal to zero.");
|
|
49
|
-
}
|
|
50
|
-
return number;
|
|
51
|
-
}
|
|
52
|
-
function requireFraction(value, path) {
|
|
53
|
-
const number = requireFinite(value, path);
|
|
54
|
-
if (number < 0 || number > 1) {
|
|
55
|
-
throw new InvalidConfigurationError(path +
|
|
56
|
-
" must be a finite fraction from 0 through 1.");
|
|
57
|
-
}
|
|
58
|
-
return number;
|
|
59
|
-
}
|
|
60
|
-
function parseVector3(value, path) {
|
|
61
|
-
const record = requireRecord(value, path, ["x", "y", "z"]);
|
|
62
|
-
return {
|
|
63
|
-
x: requireFinite(record.x, path + ".x"),
|
|
64
|
-
y: requireFinite(record.y, path + ".y"),
|
|
65
|
-
z: requireFinite(record.z, path + ".z")
|
|
66
|
-
};
|
|
67
|
-
}
|
|
68
21
|
function parseUnitDirection(value, path) {
|
|
69
22
|
const vector = parseVector3(value, path);
|
|
70
23
|
const length = hypot3(vector.x, vector.y, vector.z);
|
|
@@ -93,17 +46,6 @@ function parseUncertainty(value, path) {
|
|
|
93
46
|
}
|
|
94
47
|
throw new InvalidConfigurationError(path + ".kind is invalid.");
|
|
95
48
|
}
|
|
96
|
-
function parseLimitations(value, path) {
|
|
97
|
-
if (!Array.isArray(value)) {
|
|
98
|
-
throw new InvalidConfigurationError(path + " must be an array.");
|
|
99
|
-
}
|
|
100
|
-
const limitations = value.map((entry, index) => requireNonEmptyString(entry, path + "[" + index + "]"));
|
|
101
|
-
if (new Set(limitations).size !==
|
|
102
|
-
limitations.length) {
|
|
103
|
-
throw new InvalidConfigurationError(path + " must not contain duplicates.");
|
|
104
|
-
}
|
|
105
|
-
return limitations;
|
|
106
|
-
}
|
|
107
49
|
function parseArtifact(value, path) {
|
|
108
50
|
const record = requireRecord(value, path, ["checksumSha256", "id"]);
|
|
109
51
|
const checksumSha256 = requireNonEmptyString(record.checksumSha256, path + ".checksumSha256");
|