@photivra/engine 2.12.0 → 2.14.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (148) hide show
  1. package/CHANGELOG.md +144 -1
  2. package/CITATION.cff +1 -1
  3. package/README.md +7 -7
  4. package/SECURITY.md +1 -1
  5. package/THIRD_PARTY.md +3 -0
  6. package/dist/camera/lens-projection.js +2 -1
  7. package/dist/camera/lens-projection.js.map +1 -1
  8. package/dist/capture/dng-import.js +1 -1
  9. package/dist/capture/dng-import.js.map +1 -1
  10. package/dist/capture/export-jpeg.d.ts +1 -1
  11. package/dist/capture/export-jpeg.js +6 -4
  12. package/dist/capture/export-jpeg.js.map +1 -1
  13. package/dist/capture/host-yield-cadence.js +1 -1
  14. package/dist/capture/host-yield-cadence.js.map +1 -1
  15. package/dist/capture/native-environment-optical-stage.js +1 -1
  16. package/dist/capture/native-environment-optical-stage.js.map +1 -1
  17. package/dist/capture/native-raw.js +1 -1
  18. package/dist/capture/native-raw.js.map +1 -1
  19. package/dist/capture/packed-sensor-raw.js +3 -3
  20. package/dist/capture/packed-sensor-raw.js.map +1 -1
  21. package/dist/capture/sensor-raw-producer.js +1 -1
  22. package/dist/capture/sensor-raw-producer.js.map +1 -1
  23. package/dist/color/capture-color.js +3 -3
  24. package/dist/color/capture-color.js.map +1 -1
  25. package/dist/color/chromatic-adaptation.js +2 -2
  26. package/dist/color/chromatic-adaptation.js.map +1 -1
  27. package/dist/color/color-matching-functions.js +1 -1
  28. package/dist/color/color-matching-functions.js.map +1 -1
  29. package/dist/color/colorimetry-math.js +2 -2
  30. package/dist/color/colorimetry-math.js.map +1 -1
  31. package/dist/color/illuminants.js +3 -3
  32. package/dist/color/illuminants.js.map +1 -1
  33. package/dist/color/rgb-color-spaces.js +1 -1
  34. package/dist/color/rgb-color-spaces.js.map +1 -1
  35. package/dist/color/sensor-color-development.js +1 -1
  36. package/dist/color/sensor-color-development.js.map +1 -1
  37. package/dist/core/record-validation.js +3 -3
  38. package/dist/core/record-validation.js.map +1 -1
  39. package/dist/core/version.d.ts +1 -1
  40. package/dist/core/version.js +1 -1
  41. package/dist/core/version.js.map +1 -1
  42. package/dist/equipment/generic-prime-lenses.js +3 -3
  43. package/dist/equipment/generic-prime-lenses.js.map +1 -1
  44. package/dist/equipment/generic-tier-assets.d.ts +23 -1
  45. package/dist/equipment/generic-tier-assets.js +58 -30
  46. package/dist/equipment/generic-tier-assets.js.map +1 -1
  47. package/dist/equipment/generic-tier-presets.d.ts +6 -3
  48. package/dist/equipment/generic-tier-presets.js +26 -13
  49. package/dist/equipment/generic-tier-presets.js.map +1 -1
  50. package/dist/exposure/auto-iso-slowest-shutter.d.ts +120 -0
  51. package/dist/exposure/auto-iso-slowest-shutter.js +217 -0
  52. package/dist/exposure/auto-iso-slowest-shutter.js.map +1 -0
  53. package/dist/exposure/exposure-mode-resolver.d.ts +57 -1
  54. package/dist/exposure/exposure-mode-resolver.js +238 -33
  55. package/dist/exposure/exposure-mode-resolver.js.map +1 -1
  56. package/dist/exposure/flash-ttl.js +1 -1
  57. package/dist/exposure/flash-ttl.js.map +1 -1
  58. package/dist/exposure/flash.js +1 -1
  59. package/dist/exposure/flash.js.map +1 -1
  60. package/dist/facade/chart-material-layers.js +2 -2
  61. package/dist/facade/chart-material-layers.js.map +1 -1
  62. package/dist/facade/chart-radiance-batch.js +1 -1
  63. package/dist/facade/chart-radiance-batch.js.map +1 -1
  64. package/dist/facade/chart-scenes.d.ts +45 -8
  65. package/dist/facade/chart-scenes.js +101 -44
  66. package/dist/facade/chart-scenes.js.map +1 -1
  67. package/dist/facade/color-patches.d.ts +129 -0
  68. package/dist/facade/color-patches.js +209 -0
  69. package/dist/facade/color-patches.js.map +1 -0
  70. package/dist/facade/diffraction-provider.js +12 -13
  71. package/dist/facade/diffraction-provider.js.map +1 -1
  72. package/dist/facade/display-view-gpu.js +1 -1
  73. package/dist/facade/display-view-gpu.js.map +1 -1
  74. package/dist/facade/display-view.d.ts +27 -0
  75. package/dist/facade/display-view.js +234 -65
  76. package/dist/facade/display-view.js.map +1 -1
  77. package/dist/facade/scene-radiance.js +2 -2
  78. package/dist/facade/scene-radiance.js.map +1 -1
  79. package/dist/facade/simulate-capture.d.ts +139 -12
  80. package/dist/facade/simulate-capture.js +209 -36
  81. package/dist/facade/simulate-capture.js.map +1 -1
  82. package/dist/facade/simulate-display-view.js +2 -2
  83. package/dist/facade/simulate-display-view.js.map +1 -1
  84. package/dist/gpu/chart-composite-gpu.js +2 -2
  85. package/dist/gpu/chart-composite-gpu.js.map +1 -1
  86. package/dist/gpu/display-view-composite-material-module.js +1 -1
  87. package/dist/gpu/display-view-composite-material-module.js.map +1 -1
  88. package/dist/gpu/display-view-quality-gpu.d.ts +2 -1
  89. package/dist/gpu/display-view-quality-gpu.js +24 -14
  90. package/dist/gpu/display-view-quality-gpu.js.map +1 -1
  91. package/dist/gpu/image-kernel-execution.js +2 -2
  92. package/dist/gpu/image-kernel-execution.js.map +1 -1
  93. package/dist/gpu/temporal-sum-gpu.js +23 -23
  94. package/dist/gpu/webgpu-runtime.js +1 -1
  95. package/dist/gpu/webgpu-runtime.js.map +1 -1
  96. package/dist/gpu/wgsl-chart-composite-kernel.js +318 -318
  97. package/dist/gpu/wgsl-chart-composite-kernel.js.map +1 -1
  98. package/dist/gpu/wgsl-chart-kernel.js +117 -117
  99. package/dist/gpu/wgsl-chart-kernel.js.map +1 -1
  100. package/dist/gpu/wgsl-display-view-quality-kernel.d.ts +13 -1
  101. package/dist/gpu/wgsl-display-view-quality-kernel.js +522 -488
  102. package/dist/gpu/wgsl-display-view-quality-kernel.js.map +1 -1
  103. package/dist/gpu/wgsl-display-view-speed-kernel.js +248 -248
  104. package/dist/gpu/wgsl-display-view-speed-kernel.js.map +1 -1
  105. package/dist/gpu/wgsl-kernels.js +203 -203
  106. package/dist/gpu/wgsl-kernels.js.map +1 -1
  107. package/dist/gpu/wgsl-sensor-kernel.js +302 -302
  108. package/dist/gpu/wgsl-sensor-kernel.js.map +1 -1
  109. package/dist/index.d.ts +8 -5
  110. package/dist/index.js +6 -3
  111. package/dist/index.js.map +1 -1
  112. package/dist/motion/temporal-exposure-sum.js +1 -1
  113. package/dist/motion/temporal-exposure-sum.js.map +1 -1
  114. package/dist/optics/diffraction-psf-profile.js +4 -4
  115. package/dist/optics/diffraction-psf-profile.js.map +1 -1
  116. package/dist/optics/front-of-lens-filter.js +1 -1
  117. package/dist/optics/front-of-lens-filter.js.map +1 -1
  118. package/dist/optics/irradiance-convolution.d.ts +10 -0
  119. package/dist/optics/irradiance-convolution.js +49 -14
  120. package/dist/optics/irradiance-convolution.js.map +1 -1
  121. package/dist/output/native-capture-sdr.js +1 -1
  122. package/dist/output/native-capture-sdr.js.map +1 -1
  123. package/dist/output/png-encoder.js +2 -2
  124. package/dist/output/png-encoder.js.map +1 -1
  125. package/dist/output/print-jpeg.js +13 -10
  126. package/dist/output/print-jpeg.js.map +1 -1
  127. package/dist/output/text-metadata.d.ts +22 -2
  128. package/dist/output/text-metadata.js +58 -9
  129. package/dist/output/text-metadata.js.map +1 -1
  130. package/dist/sensor/fixed-pattern-noise.js +1 -1
  131. package/dist/sensor/fixed-pattern-noise.js.map +1 -1
  132. package/dist/sensor/readout-exposure-linkage.js +1 -1
  133. package/dist/sensor/readout-exposure-linkage.js.map +1 -1
  134. package/docs/API_REFERENCE.md +49 -1
  135. package/docs/QUICK_START.md +104 -9
  136. package/docs/USAGE.md +241 -2
  137. package/docs/api/core-version.md +1 -1
  138. package/docs/api/equipment-generic-tier-assets.md +41 -1
  139. package/docs/api/equipment-generic-tier-presets.md +11 -3
  140. package/docs/api/exports.json +172 -2
  141. package/docs/api/exposure-auto-iso-slowest-shutter.md +139 -0
  142. package/docs/api/exposure-exposure-mode-resolver.md +68 -0
  143. package/docs/api/facade-chart-scenes.md +36 -5
  144. package/docs/api/facade-color-patches.md +150 -0
  145. package/docs/api/facade-simulate-capture.md +140 -9
  146. package/docs/api/output-text-metadata.md +34 -0
  147. package/llms.txt +1 -0
  148. package/package.json +2 -2
@@ -1 +1 @@
1
- {"version":3,"file":"chart-material-layers.js","sourceRoot":"","sources":["../../src/facade/chart-material-layers.ts"],"names":[],"mappings":"AAAA,sCAAsC;AAEtC;;;;;;;;;;;;;;;;;;;GAmBG;AAEH,OAAO,EAAE,yBAAyB,EAAE,MAAM,gCAAgC,CAAC;AAC3E,OAAO,EAAE,gBAAgB,EAAE,kBAAkB,EAAE,MAAM,8BAA8B,CAAC;AACpF,OAAO,EAAE,iBAAiB,EAAE,oBAAoB,EAAE,mBAAmB,EAAmE,MAAM,mBAAmB,CAAC;AAsBlK,+EAA+E;AAC/E,MAAM,CAAC,MAAM,sBAAsB,GAAG,MAAM,CAAC,MAAM,CAAC,EAAE,MAAM,EAAE,EAAE,EAAE,MAAM,EAAE,EAAE,EAAE,CAAC,CAAC;AAChF,kCAAkC;AAClC,MAAM,CAAC,MAAM,2BAA2B,GAAG,MAAM,CAAC,MAAM,CAAC,EAAE,aAAa,EAAE,EAAE,EAAE,aAAa,EAAE,IAAI,EAAE,YAAY,EAAE,GAAG,EAAE,YAAY,EAAE,MAAM,EAAE,CAAC,CAAC;AAwC9I,MAAM,QAAQ,GAAG,qCAAqC,CAAC;AACvD,MAAM,MAAM,GAAG,CAAC,KAAc,EAAE,IAAY,EAAU,EAAE;IACtD,IAAI,OAAO,KAAK,KAAK,QAAQ,IAAI,CAAC,MAAM,CAAC,QAAQ,CAAC,KAAK,CAAC;QAAE,MAAM,IAAI,yBAAyB,CAAC,IAAI,GAAG,2BAA2B,CAAC,CAAC;IAClI,OAAO,KAAK,CAAC;AACf,CAAC,CAAC;AACF,uIAAuI;AACvI,MAAM,WAAW,GAAG,CAAC,MAAc,EAAU,EAAE,CAAC,IAAI,CAAC,GAAG,CAAC,MAAM,EAAE,MAAM,CAAC,SAAS,CAAC,GAAG,CAAC,IAAI,CAAC,EAAE,CAAC;AAE9F,SAAS,cAAc,CAAC,KAAuB,EAAE,IAAY;IAC3D,MAAM,KAAK,GAAG,KAAK,CAAC,KAAK,CAAC;IAC1B,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,KAAK,CAAC,IAAI,KAAK,CAAC,MAAM,GAAG,CAAC,IAAI,KAAK,CAAC,MAAM,GAAG,2BAA2B,CAAC,YAAY;QAAE,MAAM,IAAI,yBAAyB,CAAC,IAAI,GAAG,wBAAwB,CAAC,CAAC;IAC/K,IAAI,KAAK,GAAG,CAAC,CAAC;IACd,KAAK,MAAM,IAAI,IAAI,KAAK,EAAE,CAAC;QACzB,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,IAAI,CAAC,IAAI,IAAI,CAAC,MAAM,GAAG,CAAC,IAAI,IAAI,CAAC,MAAM,GAAG,CAAC,KAAK,CAAC;YAAE,MAAM,IAAI,yBAAyB,CAAC,IAAI,GAAG,6CAA6C,CAAC,CAAC;QAChK,KAAK,IAAI,IAAI,CAAC,MAAM,GAAG,CAAC,CAAC;IAC3B,CAAC;IACD,IAAI,KAAK,GAAG,2BAA2B,CAAC,YAAY;QAAE,MAAM,IAAI,yBAAyB,CAAC,IAAI,GAAG,6BAA6B,CAAC,CAAC;IAChI,MAAM,KAAK,GAAG,IAAI,YAAY,CAAC,CAAC,GAAG,KAAK,CAAC,CAAC;IAC1C,IAAI,IAAI,GAAG,QAAQ,EAAE,IAAI,GAAG,QAAQ,EAAE,IAAI,GAAG,CAAC,QAAQ,EAAE,IAAI,GAAG,CAAC,QAAQ,EAAE,CAAC,GAAG,CAAC,CAAC;IAChF,KAAK,MAAM,IAAI,IAAI,KAAK,EAAE,CAAC;QACzB,MAAM,CAAC,GAAG,IAAI,CAAC,MAAM,GAAG,CAAC,CAAC;QAC1B,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC;YAC3B,MAAM,EAAE,GAAG,MAAM,CAAC,IAAI,CAAC,CAAC,GAAG,CAAC,CAAC,EAAE,IAAI,GAAG,SAAS,CAAC,EAAE,EAAE,GAAG,MAAM,CAAC,IAAI,CAAC,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC,EAAE,IAAI,GAAG,SAAS,CAAC,CAAC;YACjG,MAAM,IAAI,GAAG,CAAC,GAAG,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,EAAE,EAAE,GAAG,MAAM,CAAC,IAAI,CAAC,CAAC,GAAG,IAAI,CAAC,EAAE,IAAI,GAAG,SAAS,CAAC,EAAE,EAAE,GAAG,MAAM,CAAC,IAAI,CAAC,CAAC,GAAG,IAAI,GAAG,CAAC,CAAC,EAAE,IAAI,GAAG,SAAS,CAAC,CAAC;YACvI,KAAK,CAAC,CAAC,EAAE,CAAC,GAAG,EAAE,CAAC;YAAC,KAAK,CAAC,CAAC,EAAE,CAAC,GAAG,EAAE,CAAC;YAAC,KAAK,CAAC,CAAC,EAAE,CAAC,GAAG,EAAE,CAAC;YAAC,KAAK,CAAC,CAAC,EAAE,CAAC,GAAG,EAAE,CAAC;YACnE,IAAI,GAAG,IAAI,CAAC,GAAG,CAAC,IAAI,EAAE,EAAE,CAAC,CAAC;YAAC,IAAI,GAAG,IAAI,CAAC,GAAG,CAAC,IAAI,EAAE,EAAE,CAAC,CAAC;YAAC,IAAI,GAAG,IAAI,CAAC,GAAG,CAAC,IAAI,EAAE,EAAE,CAAC,CAAC;YAAC,IAAI,GAAG,IAAI,CAAC,GAAG,CAAC,IAAI,EAAE,EAAE,CAAC,CAAC;QAC7G,CAAC;IACH,CAAC;IACD,OAAO,EAAE,IAAI,EAAE,SAAS,EAAE,GAAG,EAAE,CAAC,IAAI,EAAE,IAAI,EAAE,IAAI,EAAE,IAAI,CAAC,EAAE,KAAK,EAAE,CAAC;AACnE,CAAC;AAED,0HAA0H;AAC1H,MAAM,UAAU,cAAc,CAAC,KAAmB,EAAE,CAAS,EAAE,CAAS;IACtE,IAAI,OAAO,GAAG,CAAC,CAAC;IAChB,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,KAAK,CAAC,MAAM,EAAE,CAAC,IAAI,CAAC,EAAE,CAAC;QACzC,MAAM,EAAE,GAAG,KAAK,CAAC,CAAC,CAAE,EAAE,EAAE,GAAG,KAAK,CAAC,CAAC,GAAG,CAAC,CAAE,EAAE,EAAE,GAAG,KAAK,CAAC,CAAC,GAAG,CAAC,CAAE,EAAE,EAAE,GAAG,KAAK,CAAC,CAAC,GAAG,CAAC,CAAE,CAAC;QACjF,MAAM,IAAI,GAAG,CAAC,EAAE,GAAG,EAAE,CAAC,GAAG,CAAC,CAAC,GAAG,EAAE,CAAC,GAAG,CAAC,CAAC,GAAG,EAAE,CAAC,GAAG,CAAC,EAAE,GAAG,EAAE,CAAC,CAAC;QACzD,IAAI,EAAE,IAAI,CAAC,EAAE,CAAC;YACZ,IAAI,EAAE,GAAG,CAAC,IAAI,IAAI,GAAG,CAAC;gBAAE,OAAO,EAAE,CAAC;QACpC,CAAC;aAAM,IAAI,EAAE,IAAI,CAAC,IAAI,IAAI,GAAG,CAAC;YAAE,OAAO,EAAE,CAAC;IAC5C,CAAC;IACD,OAAO,OAAO,CAAC;AACjB,CAAC;AACD,uGAAuG;AACvG,MAAM,UAAU,aAAa,CAAC,KAA6B,EAAE,CAAS,EAAE,CAAS;IAC/E,MAAM,CAAC,GAAG,KAAK,CAAC,GAAG,CAAC;IACpB,IAAI,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,CAAC;QAAE,OAAO,KAAK,CAAC;IACtE,IAAI,KAAK,CAAC,IAAI,KAAK,SAAS,EAAE,CAAC;QAC7B,MAAM,EAAE,GAAG,CAAC,CAAC,GAAG,KAAK,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC,GAAG,KAAK,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC,GAAG,KAAK,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC,GAAG,KAAK,CAAC,OAAO,CAAC,CAAC;QACjG,OAAO,EAAE,IAAI,KAAK,CAAC,MAAM,IAAI,EAAE,IAAI,KAAK,CAAC,MAAM,CAAC;IAClD,CAAC;IACD,OAAO,cAAc,CAAC,KAAK,CAAC,KAAK,EAAE,CAAC,EAAE,CAAC,CAAC,KAAK,CAAC,CAAC;AACjD,CAAC;AAED,SAAS,YAAY,CAAC,KAAc,EAAE,IAAY,EAAE,MAAc,EAAE,SAAoD,EAAE,MAAiB;IACzI,kBAAkB,CAAC,KAAK,EAAE,IAAI,CAAC,CAAC;IAChC,MAAM,KAAK,GAAG,KAAgC,CAAC;IAC/C,KAAK,MAAM,GAAG,IAAI,MAAM,CAAC,IAAI,CAAC,KAAK,CAAC,EAAE,CAAC;QACrC,IAAI,CAAC,CAAC,MAAM,EAAE,WAAW,EAAE,YAAY,EAAE,aAAa,EAAE,QAAQ,EAAE,uBAAuB,EAAE,gBAAgB,CAAC,CAAC,QAAQ,CAAC,GAAG,CAAC;YAAE,MAAM,IAAI,yBAAyB,CAAC,UAAU,GAAG,IAAI,GAAG,UAAU,GAAG,GAAG,GAAG,GAAG,CAAC,CAAC;IAC9M,CAAC;IACD,IAAI,KAAK,CAAC,IAAI,KAAK,YAAY;QAAE,MAAM,IAAI,yBAAyB,CAAC,IAAI,GAAG,2BAA2B,CAAC,CAAC;IACzG,kBAAkB,CAAC,KAAK,CAAC,SAAS,EAAE,IAAI,GAAG,YAAY,CAAC,CAAC;IACzD,MAAM,CAAC,GAAG,KAAK,CAAC,SAAoC,CAAC;IACrD,KAAK,MAAM,GAAG,IAAI,MAAM,CAAC,IAAI,CAAC,CAAC,CAAC;QAAE,IAAI,CAAC,CAAC,IAAI,EAAE,IAAI,EAAE,IAAI,EAAE,IAAI,CAAC,CAAC,QAAQ,CAAC,GAAG,CAAC;YAAE,MAAM,IAAI,yBAAyB,CAAC,UAAU,GAAG,IAAI,GAAG,oBAAoB,GAAG,GAAG,GAAG,GAAG,CAAC,CAAC;IACzK,MAAM,EAAE,GAAG,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,IAAI,GAAG,eAAe,CAAC,EAAE,EAAE,GAAG,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,IAAI,GAAG,eAAe,CAAC,EAAE,EAAE,GAAG,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,IAAI,GAAG,eAAe,CAAC,EAAE,EAAE,GAAG,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,IAAI,GAAG,eAAe,CAAC,CAAC;IACjL,IAAI,CAAC,CAAC,EAAE,GAAG,EAAE,IAAI,EAAE,GAAG,EAAE,CAAC,IAAI,IAAI,CAAC,GAAG,CAAC,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,EAAE,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC,GAAG,GAAG,IAAI,IAAI,CAAC,GAAG,CAAC,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,EAAE,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC,GAAG,GAAG,GAAG,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,MAAM,CAAC,EAAE,CAAC;QAC5I,MAAM,IAAI,yBAAyB,CAAC,IAAI,GAAG,+DAA+D,CAAC,CAAC;IAC9G,CAAC;IACD,MAAM,UAAU,GAAG,MAAM,CAAC,KAAK,CAAC,UAAU,EAAE,IAAI,GAAG,aAAa,CAAC,EAAE,WAAW,GAAG,MAAM,CAAC,KAAK,CAAC,WAAW,EAAE,IAAI,GAAG,cAAc,CAAC,CAAC;IAClI,IAAI,CAAC,CAAC,UAAU,GAAG,CAAC,IAAI,WAAW,GAAG,CAAC,IAAI,UAAU,IAAI,GAAG,IAAI,WAAW,IAAI,GAAG,CAAC;QAAE,MAAM,IAAI,yBAAyB,CAAC,IAAI,GAAG,2CAA2C,CAAC,CAAC;IAC7K,MAAM,IAAI,GAAG,KAAK,CAAC,MAAM,CAAC;IAC1B,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,IAAI,CAAC,IAAI,IAAI,CAAC,MAAM,GAAG,CAAC,IAAI,IAAI,CAAC,MAAM,GAAG,2BAA2B,CAAC,aAAa;QAAE,MAAM,IAAI,yBAAyB,CAAC,IAAI,GAAG,qCAAqC,CAAC,CAAC;IAC1L,MAAM,MAAM,GAAG,IAAI,CAAC,GAAG,CAAC,CAAC,KAAc,EAAE,KAAa,EAA0B,EAAE;QAChF,MAAM,KAAK,GAAG,IAAI,GAAG,UAAU,GAAG,KAAK,GAAG,GAAG,CAAC;QAC9C,kBAAkB,CAAC,KAAK,EAAE,KAAK,CAAC,CAAC;QACjC,MAAM,CAAC,GAAG,KAAgC,CAAC;QAC3C,IAAI,CAAC,CAAC,IAAI,KAAK,SAAS,EAAE,CAAC;YACzB,KAAK,MAAM,GAAG,IAAI,MAAM,CAAC,IAAI,CAAC,CAAC,CAAC;gBAAE,IAAI,GAAG,KAAK,MAAM,IAAI,GAAG,KAAK,OAAO;oBAAE,MAAM,IAAI,yBAAyB,CAAC,UAAU,GAAG,KAAK,GAAG,UAAU,GAAG,GAAG,GAAG,GAAG,CAAC,CAAC;YAC1J,OAAO,cAAc,CAAC,CAAgC,EAAE,KAAK,CAAC,CAAC;QACjE,CAAC;QACD,IAAI,CAAC,CAAC,IAAI,KAAK,SAAS;YAAE,MAAM,IAAI,yBAAyB,CAAC,KAAK,GAAG,mCAAmC,CAAC,CAAC;QAC3G,KAAK,MAAM,GAAG,IAAI,MAAM,CAAC,IAAI,CAAC,CAAC,CAAC;YAAE,IAAI,CAAC,CAAC,MAAM,EAAE,SAAS,EAAE,SAAS,EAAE,aAAa,EAAE,aAAa,CAAC,CAAC,QAAQ,CAAC,GAAG,CAAC;gBAAE,MAAM,IAAI,yBAAyB,CAAC,UAAU,GAAG,KAAK,GAAG,UAAU,GAAG,GAAG,GAAG,GAAG,CAAC,CAAC;QACpM,MAAM,EAAE,GAAG,MAAM,CAAC,CAAC,CAAC,OAAO,EAAE,KAAK,GAAG,UAAU,CAAC,EAAE,EAAE,GAAG,MAAM,CAAC,CAAC,CAAC,OAAO,EAAE,KAAK,GAAG,UAAU,CAAC,CAAC;QAC7F,MAAM,KAAK,GAAG,MAAM,CAAC,CAAC,CAAC,WAAW,EAAE,KAAK,GAAG,cAAc,CAAC,EAAE,KAAK,GAAG,MAAM,CAAC,CAAC,CAAC,WAAW,EAAE,KAAK,GAAG,cAAc,CAAC,CAAC;QACnH,IAAI,CAAC,CAAC,KAAK,IAAI,CAAC,IAAI,KAAK,GAAG,KAAK,CAAC;YAAE,MAAM,IAAI,yBAAyB,CAAC,KAAK,GAAG,uCAAuC,CAAC,CAAC;QACzH,OAAO,EAAE,IAAI,EAAE,SAAS,EAAE,GAAG,EAAE,CAAC,EAAE,GAAG,KAAK,EAAE,EAAE,GAAG,KAAK,EAAE,EAAE,GAAG,KAAK,EAAE,EAAE,GAAG,KAAK,CAAC,EAAE,OAAO,EAAE,EAAE,EAAE,OAAO,EAAE,EAAE,EAAE,MAAM,EAAE,KAAK,GAAG,KAAK,EAAE,MAAM,EAAE,KAAK,GAAG,KAAK,EAAE,CAAC;IAC5J,CAAC,CAAC,CAAC;IACH,KAAK,MAAM,KAAK,IAAI,MAAM,EAAE,CAAC;QAC3B,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,KAAK,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC,IAAI,GAAG,CAAC;YAAE,MAAM,IAAI,yBAAyB,CAAC,IAAI,GAAG,iDAAiD,CAAC,CAAC;IACjJ,CAAC;IACD,MAAM,kBAAkB,GAAG,SAAS,CAAC,MAAM,CAAC;IAC5C,SAAS,CAAC,IAAI,CAAC,oBAAoB,CAAC,KAAK,CAAC,qBAAqB,EAAE,IAAI,GAAG,wBAAwB,CAAC,CAAC,CAAC;IACnG,MAAM,CAAC,IAAI,CAAC,OAAO,KAAK,CAAC,qBAAqB,KAAK,QAAQ,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC,KAAK,CAAC,qBAAqB,CAAC,CAAC;IACvG,MAAM,WAAW,GAAG,SAAS,CAAC,MAAM,CAAC;IACrC,SAAS,CAAC,IAAI,CAAC,oBAAoB,CAAC,KAAK,CAAC,cAAc,EAAE,IAAI,GAAG,iBAAiB,CAAC,CAAC,CAAC;IACrF,MAAM,CAAC,IAAI,CAAC,OAAO,KAAK,CAAC,cAAc,KAAK,QAAQ,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC,KAAK,CAAC,cAAc,CAAC,CAAC;IACzF,kHAAkH;IAClH,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,GAAG,sBAAsB,EAAE,SAAS,GAAG,UAAU,GAAG,MAAM,EAAE,UAAU,GAAG,WAAW,GAAG,MAAM,CAAC;IACtH,MAAM,OAAO,GAAG,IAAI,CAAC,GAAG,CAAC,UAAU,EAAE,GAAG,MAAM,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,IAAI,CAAC,GAAG,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,EAAE,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;IAC7G,MAAM,OAAO,GAAG,IAAI,CAAC,GAAG,CAAC,WAAW,EAAE,GAAG,MAAM,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,IAAI,CAAC,GAAG,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,EAAE,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;IAC9G,IAAI,CAAC,CAAC,SAAS,GAAG,WAAW,CAAC,OAAO,CAAC,IAAI,UAAU,GAAG,WAAW,CAAC,OAAO,CAAC,CAAC;QAAE,MAAM,IAAI,yBAAyB,CAAC,IAAI,GAAG,qEAAqE,CAAC,CAAC;IAChM,MAAM,KAAK,GAAkB,EAAE,CAAC;IAChC,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,MAAM,EAAE,CAAC,EAAE,EAAE,CAAC;QAChC,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,MAAM,EAAE,CAAC,EAAE,EAAE,CAAC;YAChC,MAAM,EAAE,GAAG,CAAC,CAAC,GAAG,CAAC,CAAC,GAAG,SAAS,EAAE,EAAE,GAAG,CAAC,CAAC,GAAG,CAAC,CAAC,GAAG,SAAS,EAAE,EAAE,GAAG,CAAC,CAAC,GAAG,CAAC,CAAC,GAAG,UAAU,EAAE,EAAE,GAAG,CAAC,CAAC,GAAG,CAAC,CAAC,GAAG,UAAU,EAAE,MAAM,GAAa,EAAE,CAAC;YACtI,MAAM,CAAC,OAAO,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,GAAG,IAAI,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,IAAI,EAAE,IAAI,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,IAAI,EAAE,IAAI,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,IAAI,EAAE,IAAI,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,IAAI,EAAE;gBAAE,MAAM,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;YACxH,KAAK,CAAC,IAAI,CAAC,WAAW,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC,CAAC;QACvC,CAAC;IACH,CAAC;IACD,MAAM,MAAM,GAAG,UAAU,GAAG,CAAC,EAAE,GAAG,EAAE,CAAC,EAAE,MAAM,GAAG,WAAW,GAAG,CAAC,EAAE,GAAG,EAAE,CAAC,CAAC;IACxE,OAAO,MAAM,CAAC,MAAM,CAAC,EAAE,SAAS,EAAE,MAAM,CAAC,MAAM,CAAC,EAAE,EAAE,EAAE,EAAE,EAAE,EAAE,EAAE,EAAE,EAAE,CAAC,EAAE,UAAU,EAAE,WAAW,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,CAAC,MAAM,CAAC,MAAM,CAAC,EAAE,MAAM,EAAE,MAAM,EAAE,SAAS,EAAE,UAAU;QAChL,KAAK,EAAE,MAAM,CAAC,MAAM,CAAC,KAAK,CAAC,EAAE,kBAAkB,EAAE,WAAW;QAC5D,aAAa,CAAC,CAAS,EAAE,CAAS;YAChC,IAAI,CAAC,GAAG,IAAI,CAAC,KAAK,CAAC,CAAC,GAAG,SAAS,CAAC,EAAE,CAAC,GAAG,IAAI,CAAC,KAAK,CAAC,CAAC,GAAG,UAAU,CAAC,CAAC;YAClE,IAAI,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC;gBAAE,CAAC,GAAG,CAAC,CAAC;iBAAM,IAAI,CAAC,IAAI,MAAM;gBAAE,CAAC,GAAG,MAAM,GAAG,CAAC,CAAC;YAC1D,IAAI,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC;gBAAE,CAAC,GAAG,CAAC,CAAC;iBAAM,IAAI,CAAC,IAAI,MAAM;gBAAE,CAAC,GAAG,MAAM,GAAG,CAAC,CAAC;YAC1D,MAAM,IAAI,GAAG,KAAK,CAAC,CAAC,GAAG,MAAM,GAAG,CAAC,CAAE,CAAC;YACpC,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,IAAI,CAAC,MAAM,EAAE,CAAC,EAAE;gBAAE,IAAI,aAAa,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC,CAAE,CAAE,EAAE,CAAC,EAAE,CAAC,CAAC;oBAAE,OAAO,IAAI,CAAC;YAC9F,OAAO,KAAK,CAAC;QACf,CAAC,EAAE,CAAC,CAAC;AACT,CAAC;AAED;;;;GAIG;AACH,MAAM,UAAU,0BAA0B,CAAC,KAAyD;IAClG,gBAAgB,CAAC,KAAK,EAAE,4BAA4B,EAAE,CAAC,OAAO,EAAE,QAAQ,CAAC,CAAC,CAAC;IAC3E,MAAM,EAAE,KAAK,EAAE,MAAM,EAAE,GAAG,KAAK,CAAC;IAChC,kBAAkB,CAAC,KAAK,EAAE,OAAO,CAAC,CAAC;IACnC,MAAM,MAAM,GAAG,KAA2C,CAAC;IAC3D,KAAK,MAAM,GAAG,IAAI,MAAM,CAAC,IAAI,CAAC,MAAM,CAAC;QAAE,IAAI,CAAC,CAAC,MAAM,EAAE,SAAS,EAAE,OAAO,EAAE,QAAQ,CAAC,CAAC,QAAQ,CAAC,GAAG,CAAC;YAAE,MAAM,IAAI,yBAAyB,CAAC,uBAAuB,GAAG,GAAG,GAAG,GAAG,CAAC,CAAC;IAC3K,IAAI,MAAM,CAAC,IAAI,KAAK,iBAAiB;QAAE,MAAM,IAAI,yBAAyB,CAAC,qCAAqC,CAAC,CAAC;IAClH,IAAI,OAAO,MAAM,CAAC,OAAO,KAAK,QAAQ,IAAI,CAAC,QAAQ,CAAC,IAAI,CAAC,MAAM,CAAC,OAAO,CAAC;QAAE,MAAM,IAAI,yBAAyB,CAAC,iDAAiD,CAAC,CAAC;IACjK,IAAI,OAAO,MAAM,KAAK,QAAQ,IAAI,CAAC,MAAM,CAAC,QAAQ,CAAC,MAAM,CAAC,IAAI,MAAM,IAAI,CAAC;QAAE,MAAM,IAAI,yBAAyB,CAAC,gCAAgC,CAAC,CAAC;IACjJ,MAAM,KAAK,GAAG,iBAAiB,CAAC,EAAE,KAAK,EAAE,MAAM,CAAC,KAAmB,EAAE,MAAM,EAAE,CAAC,CAAC;IAC/E,MAAM,IAAI,GAAG,MAAM,CAAC,MAAM,CAAC;IAC3B,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,IAAI,CAAC,IAAI,IAAI,CAAC,MAAM,GAAG,CAAC,IAAI,IAAI,CAAC,MAAM,GAAG,2BAA2B,CAAC,aAAa;QAAE,MAAM,IAAI,yBAAyB,CAAC,6CAA6C,CAAC,CAAC;IAC3L,MAAM,SAAS,GAA8C,CAAC,GAAG,KAAK,CAAC,SAAS,CAAC,EAAE,MAAM,GAAc,CAAC,GAAG,mBAAmB,CAAC,KAAK,CAAC,CAAC,CAAC;IACvI,MAAM,MAAM,GAAG,IAAI,CAAC,GAAG,CAAC,CAAC,KAAc,EAAE,KAAa,EAAE,EAAE,CAAC,YAAY,CAAC,KAAK,EAAE,SAAS,GAAG,KAAK,GAAG,GAAG,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,CAAC,CAAC,CAAC;IACpI,MAAM,UAAU,GAAG,CAAC,CAAS,EAAE,CAAS,EAAU,EAAE;QAClD,KAAK,IAAI,CAAC,GAAG,MAAM,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC,IAAI,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC;YAC5C,MAAM,KAAK,GAAG,MAAM,CAAC,CAAC,CAAE,EAAE,CAAC,GAAG,KAAK,CAAC,SAAS,CAAC;YAC9C,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE;gBAAE,SAAS;YAC3D,OAAO,KAAK,CAAC,aAAa,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,EAAE,CAAC,GAAG,KAAK,CAAC,MAAM,EAAE,CAAC,CAAC,CAAC,EAAE,GAAG,CAAC,CAAC,GAAG,KAAK,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,WAAW,CAAC,CAAC,CAAC,KAAK,CAAC,kBAAkB,CAAC;QAClI,CAAC;QACD,OAAO,KAAK,CAAC,UAAU,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC;IAChC,CAAC,CAAC;IACF,MAAM,eAAe,GAAG,SAAS,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,CAAC,IAAI,KAAK,SAAS,CAAC,CAAC,CAAC,CAAC,CAAC,WAAW,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAqB,CAAC,CAAC,CAAC;IACxH,MAAM,WAAW,GAAwB,MAAM,CAAC,MAAM,CAAC,EAAE,IAAI,EAAE,mBAA4B,EAAE,OAAO,EAAE,MAAM,CAAC,OAAO,EAAE,SAAS,EAAE,MAAM,CAAC,MAAM,CAAC,eAAe,CAAC;QAC7J,UAAU,EAAE,CAAC,CAA+B,EAAE,EAAE,CAAC,UAAU,CAAC,CAAC,CAAC,MAAM,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,MAAM,IAAI,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC;IACnG,OAAO,MAAM,CAAC,MAAM,CAAC,EAAE,IAAI,EAAE,iBAA0B,EAAE,OAAO,EAAE,MAAM,CAAC,OAAO,EAAE,KAAK,EAAE,MAAM,EAAE,MAAM,CAAC,MAAM,CAAC,MAAM,CAAC,EAAE,SAAS,EAAE,MAAM,CAAC,MAAM,CAAC,SAAS,CAAC;QACzJ,cAAc,EAAE,MAAM,CAAC,MAAM,CAAC,MAAM,CAAC,EAAE,UAAU,EAAE,WAAW,EAAE,CAAC,CAAC;AACtE,CAAC","sourcesContent":["// SPDX-License-Identifier: Apache-2.0\n\n/**\n * Declared material scenes (#477): an engine chart under shape-mask layers, given as data rather than as a\n * `materialAt` function, so that both the float64 reference and the `webgpu-f32` chart stage can evaluate\n * them. An application that prints a label on a chart (a logo and a line of text as filled polygons and\n * stroked rings, in the label's own units) describes it here; the engine holds no label of its own.\n *\n * A layer maps its mask box, [0, unitsWidth] × [0, unitsHeight] with y down, onto a frame rectangle. Inside\n * that rectangle the layer decides the material: the ink material where any of its shapes contains the\n * point, its background material elsewhere. Later layers cover earlier ones, and the chart shows outside\n * every layer. Shapes are polygons under the non-zero winding rule (several rings per shape; a stroked\n * polyline is its rectangles as rings of one orientation) and annuli (stroked circles).\n *\n * Each layer carries a cell index of {@link CHART_MASK_INDEX_GRAIN} cells over its box: a cell lists the\n * shapes whose bounding box meets the cell grown by one cell on every side, so `containsUnits` tests only\n * those. A computed cell can be off by one from the true one only through the rounding of one subtraction\n * and one multiplication, far less than a cell (the grain is checked against the coordinates' magnitude\n * when the layer is resolved), and a shape left out of a cell's list lies a whole cell away from any point\n * that resolves to it, so the indexed test gives the full test's answer at every point. The GPU uses the same\n * index (docs/WEBGPU.md, \"Scene radiance on the GPU\").\n */\n\nimport { InvalidConfigurationError } from \"../core/configuration-error.js\";\nimport { requireInputKeys, requireInputObject } from \"../core/record-validation.js\";\nimport { resolveChartScene, resolveChartMaterial, chartMaterialInputs, type ChartReflectance, type ChartScene, type ResolvedChartScene } from \"./chart-scenes.js\";\nimport type { CallerMaterialScene, SceneMaterialPoint } from \"./scene-radiance.js\";\n\n/** A filled polygon: rings as flat [x0, y0, x1, y1, …] in mask units (y down), non-zero winding over all rings. */\nexport interface ChartMaskPolygon { kind: \"polygon\"; rings: readonly (readonly number[])[] }\n/** A stroked circle: the points at distance innerRadius ≤ d ≤ outerRadius from the centre, mask units. */\nexport interface ChartMaskAnnulus { kind: \"annulus\"; centerX: number; centerY: number; innerRadius: number; outerRadius: number }\nexport type ChartMaskShape = ChartMaskPolygon | ChartMaskAnnulus;\n/** A shape mask printed over the chart: its box [0, unitsWidth] × [0, unitsHeight] (y down) fills `rectangle` (frame units, v up). */\nexport interface ChartMaskLayer {\n kind: \"shape-mask\";\n rectangle: { u0: number; v0: number; u1: number; v1: number };\n unitsWidth: number;\n unitsHeight: number;\n /** 1 to 4096 shapes, in order; the ink material where any contains the point. */\n shapes: readonly ChartMaskShape[];\n backgroundReflectance: ChartReflectance;\n inkReflectance: ChartReflectance;\n}\n/** A chart under 1 to 16 shape-mask layers, as data; `resolveChartMaterialLayers` evaluates it. */\nexport interface ChartMaterialLayerScene { kind: \"material-layers\"; sceneId: string; chart: ChartScene; layers: readonly ChartMaskLayer[] }\n\n/** The cell index grain of every layer: cells across and down the mask box. */\nexport const CHART_MASK_INDEX_GRAIN = Object.freeze({ cellsX: 64, cellsY: 16 });\n/** Limits of a declared scene. */\nexport const CHART_MATERIAL_LAYER_LIMITS = Object.freeze({ maximumLayers: 16, maximumShapes: 4096, maximumRings: 256, maximumEdges: 65_536 });\n\n/** Internal: a shape with its bounding box and flattened edges (polygon) or squared radii (annulus). */\nexport type ResolvedChartMaskShape =\n | { kind: \"polygon\"; box: readonly [number, number, number, number]; edges: Float64Array }\n | { kind: \"annulus\"; box: readonly [number, number, number, number]; centerX: number; centerY: number; inner2: number; outer2: number };\nexport interface ResolvedChartMaskLayer {\n rectangle: { u0: number; v0: number; u1: number; v1: number };\n unitsWidth: number;\n unitsHeight: number;\n /** Mask units per frame unit: unitsWidth / (u1 − u0) and unitsHeight / (v1 − v0). */\n scaleX: number;\n scaleY: number;\n shapes: readonly ResolvedChartMaskShape[];\n cellsX: number;\n cellsY: number;\n cellWidth: number;\n cellHeight: number;\n /** Per cell (row by row), the shape indices whose bounding box meets the cell grown by one cell. */\n cells: readonly Uint32Array[];\n backgroundMaterial: number;\n inkMaterial: number;\n /** Whether a point in mask units is ink (through the cell index). */\n containsUnits(x: number, y: number): boolean;\n}\nexport interface ResolvedChartMaterialLayers {\n kind: \"material-layers\";\n sceneId: string;\n /** The chart under the layers; its materials come first in `materials`. */\n chart: ResolvedChartScene;\n layers: readonly ResolvedChartMaskLayer[];\n materials: ResolvedChartScene[\"materials\"];\n /** Internal: the caller input behind each material (undefined for an engine neutral), for the scene digest. */\n materialInputs: readonly unknown[];\n /** Material index at a frame point (u right, v up): the topmost layer whose rectangle holds the point, else the chart. */\n materialAt(u: number, v: number): number;\n /** The same scene as a caller material scene for `simulateCapture` and the display view (chart-local coordinates when the chart has a size). */\n callerScene: CallerMaterialScene;\n}\n\nconst SCENE_ID = /^[A-Za-z0-9][A-Za-z0-9._:-]{0,63}$/u;\nconst finite = (value: unknown, name: string): number => {\n if (typeof value !== \"number\" || !Number.isFinite(value)) throw new InvalidConfigurationError(name + \" must be a finite number.\");\n return value;\n};\n/** The smallest cell the one-cell margin covers: the rounding of (x − 0)·scale is a few units in the last place of the coordinates. */\nconst minimumCell = (extent: number): number => Math.max(extent, Number.MIN_VALUE) * 2 ** -20;\n\nfunction resolvePolygon(shape: ChartMaskPolygon, name: string): ResolvedChartMaskShape {\n const rings = shape.rings;\n if (!Array.isArray(rings) || rings.length < 1 || rings.length > CHART_MATERIAL_LAYER_LIMITS.maximumRings) throw new InvalidConfigurationError(name + \" needs 1 to 256 rings.\");\n let count = 0;\n for (const ring of rings) {\n if (!Array.isArray(ring) || ring.length < 6 || ring.length % 2 !== 0) throw new InvalidConfigurationError(name + \" rings need at least three (x, y) vertices.\");\n count += ring.length / 2;\n }\n if (count > CHART_MATERIAL_LAYER_LIMITS.maximumEdges) throw new InvalidConfigurationError(name + \" has more than 65536 edges.\");\n const edges = new Float64Array(4 * count);\n let minX = Infinity, minY = Infinity, maxX = -Infinity, maxY = -Infinity, e = 0;\n for (const ring of rings) {\n const n = ring.length / 2;\n for (let k = 0; k < n; k++) {\n const x0 = finite(ring[2 * k], name + \" vertex\"), y0 = finite(ring[2 * k + 1], name + \" vertex\");\n const next = k + 1 === n ? 0 : k + 1, x1 = finite(ring[2 * next], name + \" vertex\"), y1 = finite(ring[2 * next + 1], name + \" vertex\");\n edges[e++] = x0; edges[e++] = y0; edges[e++] = x1; edges[e++] = y1;\n minX = Math.min(minX, x0); minY = Math.min(minY, y0); maxX = Math.max(maxX, x0); maxY = Math.max(maxY, y0);\n }\n }\n return { kind: \"polygon\", box: [minX, minY, maxX, maxY], edges };\n}\n\n/** Non-zero winding over the edges (x0, y0, x1, y1), as the reference evaluates it; the GPU runs the same comparisons. */\nexport function polygonWinding(edges: Float64Array, x: number, y: number): number {\n let winding = 0;\n for (let k = 0; k < edges.length; k += 4) {\n const x0 = edges[k]!, y0 = edges[k + 1]!, x1 = edges[k + 2]!, y1 = edges[k + 3]!;\n const side = (x1 - x0) * (y - y0) - (x - x0) * (y1 - y0);\n if (y0 <= y) {\n if (y1 > y && side > 0) winding++;\n } else if (y1 <= y && side < 0) winding--;\n }\n return winding;\n}\n/** Whether a resolved shape contains a point in mask units (the full test, without the cell index). */\nexport function shapeContains(shape: ResolvedChartMaskShape, x: number, y: number): boolean {\n const b = shape.box;\n if (!(x >= b[0] && x <= b[2] && y >= b[1] && y <= b[3])) return false;\n if (shape.kind === \"annulus\") {\n const d2 = (x - shape.centerX) * (x - shape.centerX) + (y - shape.centerY) * (y - shape.centerY);\n return d2 >= shape.inner2 && d2 <= shape.outer2;\n }\n return polygonWinding(shape.edges, x, y) !== 0;\n}\n\nfunction resolveLayer(value: unknown, name: string, aspect: number, materials: ResolvedChartScene[\"materials\"][number][], inputs: unknown[]): ResolvedChartMaskLayer {\n requireInputObject(value, name);\n const layer = value as Record<string, unknown>;\n for (const key of Object.keys(layer)) {\n if (![\"kind\", \"rectangle\", \"unitsWidth\", \"unitsHeight\", \"shapes\", \"backgroundReflectance\", \"inkReflectance\"].includes(key)) throw new InvalidConfigurationError(\"Unknown \" + name + \" field: \" + key + \".\");\n }\n if (layer.kind !== \"shape-mask\") throw new InvalidConfigurationError(name + \".kind must be shape-mask.\");\n requireInputObject(layer.rectangle, name + \".rectangle\");\n const r = layer.rectangle as Record<string, unknown>;\n for (const key of Object.keys(r)) if (![\"u0\", \"v0\", \"u1\", \"v1\"].includes(key)) throw new InvalidConfigurationError(\"Unknown \" + name + \".rectangle field: \" + key + \".\");\n const u0 = finite(r.u0, name + \".rectangle.u0\"), v0 = finite(r.v0, name + \".rectangle.v0\"), u1 = finite(r.u1, name + \".rectangle.u1\"), v1 = finite(r.v1, name + \".rectangle.v1\");\n if (!(u1 > u0 && v1 > v0) || Math.max(Math.abs(u0), Math.abs(u1)) > 1e6 || Math.max(Math.abs(v0), Math.abs(v1)) > 1e6 * Math.max(1, aspect)) {\n throw new InvalidConfigurationError(name + \".rectangle needs u0 < u1 and v0 < v1 within 10^6 frame units.\");\n }\n const unitsWidth = finite(layer.unitsWidth, name + \".unitsWidth\"), unitsHeight = finite(layer.unitsHeight, name + \".unitsHeight\");\n if (!(unitsWidth > 0 && unitsHeight > 0 && unitsWidth <= 1e9 && unitsHeight <= 1e9)) throw new InvalidConfigurationError(name + \" units must be positive and at most 10^9.\");\n const list = layer.shapes;\n if (!Array.isArray(list) || list.length < 1 || list.length > CHART_MATERIAL_LAYER_LIMITS.maximumShapes) throw new InvalidConfigurationError(name + \".shapes must list 1 to 4096 shapes.\");\n const shapes = list.map((shape: unknown, index: number): ResolvedChartMaskShape => {\n const label = name + \".shapes[\" + index + \"]\";\n requireInputObject(shape, label);\n const s = shape as Record<string, unknown>;\n if (s.kind === \"polygon\") {\n for (const key of Object.keys(s)) if (key !== \"kind\" && key !== \"rings\") throw new InvalidConfigurationError(\"Unknown \" + label + \" field: \" + key + \".\");\n return resolvePolygon(s as unknown as ChartMaskPolygon, label);\n }\n if (s.kind !== \"annulus\") throw new InvalidConfigurationError(label + \".kind must be polygon or annulus.\");\n for (const key of Object.keys(s)) if (![\"kind\", \"centerX\", \"centerY\", \"innerRadius\", \"outerRadius\"].includes(key)) throw new InvalidConfigurationError(\"Unknown \" + label + \" field: \" + key + \".\");\n const cx = finite(s.centerX, label + \".centerX\"), cy = finite(s.centerY, label + \".centerY\");\n const inner = finite(s.innerRadius, label + \".innerRadius\"), outer = finite(s.outerRadius, label + \".outerRadius\");\n if (!(inner >= 0 && outer > inner)) throw new InvalidConfigurationError(label + \" needs 0 ≤ innerRadius < outerRadius.\");\n return { kind: \"annulus\", box: [cx - outer, cy - outer, cx + outer, cy + outer], centerX: cx, centerY: cy, inner2: inner * inner, outer2: outer * outer };\n });\n for (const shape of shapes) {\n if (!shape.box.every((c) => Math.abs(c) <= 1e9)) throw new InvalidConfigurationError(name + \" shape coordinates must stay within 10^9 units.\");\n }\n const backgroundMaterial = materials.length;\n materials.push(resolveChartMaterial(layer.backgroundReflectance, name + \".backgroundReflectance\"));\n inputs.push(typeof layer.backgroundReflectance === \"number\" ? undefined : layer.backgroundReflectance);\n const inkMaterial = materials.length;\n materials.push(resolveChartMaterial(layer.inkReflectance, name + \".inkReflectance\"));\n inputs.push(typeof layer.inkReflectance === \"number\" ? undefined : layer.inkReflectance);\n // The cell index over the mask box; the grain must stay large against the coordinates' rounding (see the header).\n const { cellsX, cellsY } = CHART_MASK_INDEX_GRAIN, cellWidth = unitsWidth / cellsX, cellHeight = unitsHeight / cellsY;\n const extentX = Math.max(unitsWidth, ...shapes.map((s) => Math.max(Math.abs(s.box[0]), Math.abs(s.box[2]))));\n const extentY = Math.max(unitsHeight, ...shapes.map((s) => Math.max(Math.abs(s.box[1]), Math.abs(s.box[3]))));\n if (!(cellWidth > minimumCell(extentX) && cellHeight > minimumCell(extentY))) throw new InvalidConfigurationError(name + \": the shapes extend too far beyond the mask box for its cell index.\");\n const cells: Uint32Array[] = [];\n for (let j = 0; j < cellsY; j++) {\n for (let i = 0; i < cellsX; i++) {\n const x0 = (i - 1) * cellWidth, x1 = (i + 2) * cellWidth, y0 = (j - 1) * cellHeight, y1 = (j + 2) * cellHeight, listed: number[] = [];\n shapes.forEach((s, k) => { if (s.box[0] <= x1 && s.box[2] >= x0 && s.box[1] <= y1 && s.box[3] >= y0) listed.push(k); });\n cells.push(Uint32Array.from(listed));\n }\n }\n const scaleX = unitsWidth / (u1 - u0), scaleY = unitsHeight / (v1 - v0);\n return Object.freeze({ rectangle: Object.freeze({ u0, v0, u1, v1 }), unitsWidth, unitsHeight, scaleX, scaleY, shapes: Object.freeze(shapes), cellsX, cellsY, cellWidth, cellHeight,\n cells: Object.freeze(cells), backgroundMaterial, inkMaterial,\n containsUnits(x: number, y: number): boolean {\n let i = Math.floor(x / cellWidth), j = Math.floor(y / cellHeight);\n if (!(i > 0)) i = 0; else if (i >= cellsX) i = cellsX - 1;\n if (!(j > 0)) j = 0; else if (j >= cellsY) j = cellsY - 1;\n const list = cells[j * cellsX + i]!;\n for (let k = 0; k < list.length; k++) if (shapeContains(shapes[list[k]!]!, x, y)) return true;\n return false;\n } });\n}\n\n/**\n * Validates a declared material scene and resolves its chart (in a frame of `aspect` = height / width) and its\n * layers. `materialAt` is the float64 reference the GPU stage is checked against, and `callerScene` is the same\n * scene for `simulateCapture`'s `scene` option.\n */\nexport function resolveChartMaterialLayers(input: { scene: ChartMaterialLayerScene; aspect: number }): ResolvedChartMaterialLayers {\n requireInputKeys(input, \"resolveChartMaterialLayers\", [\"scene\", \"aspect\"]);\n const { scene, aspect } = input;\n requireInputObject(scene, \"scene\");\n const record = scene as unknown as Record<string, unknown>;\n for (const key of Object.keys(record)) if (![\"kind\", \"sceneId\", \"chart\", \"layers\"].includes(key)) throw new InvalidConfigurationError(\"Unknown scene field: \" + key + \".\");\n if (record.kind !== \"material-layers\") throw new InvalidConfigurationError(\"scene.kind must be material-layers.\");\n if (typeof record.sceneId !== \"string\" || !SCENE_ID.test(record.sceneId)) throw new InvalidConfigurationError(\"A material-layers scene needs a public sceneId.\");\n if (typeof aspect !== \"number\" || !Number.isFinite(aspect) || aspect <= 0) throw new InvalidConfigurationError(\"Chart aspect must be positive.\");\n const chart = resolveChartScene({ scene: record.chart as ChartScene, aspect });\n const list = record.layers;\n if (!Array.isArray(list) || list.length < 1 || list.length > CHART_MATERIAL_LAYER_LIMITS.maximumLayers) throw new InvalidConfigurationError(\"layers must list 1 to 16 shape-mask layers.\");\n const materials: ResolvedChartScene[\"materials\"][number][] = [...chart.materials], inputs: unknown[] = [...chartMaterialInputs(chart)];\n const layers = list.map((layer: unknown, index: number) => resolveLayer(layer, \"layers[\" + index + \"]\", aspect, materials, inputs));\n const materialAt = (u: number, v: number): number => {\n for (let l = layers.length - 1; l >= 0; l--) {\n const layer = layers[l]!, r = layer.rectangle;\n if (u < r.u0 || u > r.u1 || v < r.v0 || v > r.v1) continue;\n return layer.containsUnits((u - r.u0) * layer.scaleX, (r.v1 - v) * layer.scaleY) ? layer.inkMaterial : layer.backgroundMaterial;\n }\n return chart.materialAt(u, v);\n };\n const callerMaterials = materials.map((m, k) => (m.kind === \"neutral\" ? m.reflectance : inputs[k] as ChartReflectance));\n const callerScene: CallerMaterialScene = Object.freeze({ kind: \"material-function\" as const, sceneId: record.sceneId, materials: Object.freeze(callerMaterials),\n materialAt: (p: Readonly<SceneMaterialPoint>) => materialAt(p.chartU ?? p.u, p.chartV ?? p.v) });\n return Object.freeze({ kind: \"material-layers\" as const, sceneId: record.sceneId, chart, layers: Object.freeze(layers), materials: Object.freeze(materials),\n materialInputs: Object.freeze(inputs), materialAt, callerScene });\n}\n"]}
1
+ {"version":3,"file":"chart-material-layers.js","sourceRoot":"","sources":["../../src/facade/chart-material-layers.ts"],"names":[],"mappings":"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","sourcesContent":["// SPDX-License-Identifier: Apache-2.0\n\n/**\n * Declared material scenes (#477): an engine chart under shape-mask layers, given as data rather than as a\n * `materialAt` function, so that both the float64 reference and the `webgpu-f32` chart stage can evaluate\n * them. An application that prints a label on a chart (a logo and a line of text as filled polygons and\n * stroked rings, in the label's own units) describes it here; the engine holds no label of its own.\n *\n * A layer maps its mask box, [0, unitsWidth] × [0, unitsHeight] with y down, onto a frame rectangle. Inside\n * that rectangle the layer decides the material: the ink material where any of its shapes contains the\n * point, its background material elsewhere. Later layers cover earlier ones, and the chart shows outside\n * every layer. Shapes are polygons under the non-zero winding rule (several rings per shape; a stroked\n * polyline is its rectangles as rings of one orientation) and annuli (stroked circles).\n *\n * Each layer carries a cell index of {@link CHART_MASK_INDEX_GRAIN} cells over its box: a cell lists the\n * shapes whose bounding box meets the cell grown by one cell on every side, so `containsUnits` tests only\n * those. A computed cell can be off by one from the true one only through the rounding of one subtraction\n * and one multiplication, far less than a cell (the grain is checked against the coordinates' magnitude\n * when the layer is resolved), and a shape left out of a cell's list lies a whole cell away from any point\n * that resolves to it, so the indexed test gives the full test's answer at every point. The GPU uses the same\n * index (docs/WEBGPU.md, \"Scene radiance on the GPU\").\n */\n\nimport { InvalidConfigurationError } from \"../core/configuration-error.js\";\nimport { requireInputKeys, requireInputObject } from \"../core/record-validation.js\";\nimport { resolveChartScene, resolveChartMaterial, chartMaterialInputs, type ChartReflectance, type ChartScene, type ResolvedChartScene } from \"./chart-scenes.js\";\nimport type { CallerMaterialScene, SceneMaterialPoint } from \"./scene-radiance.js\";\n\n/** A filled polygon: rings as flat [x0, y0, x1, y1, …] in mask units (y down), non-zero winding over all rings. */\nexport interface ChartMaskPolygon { kind: \"polygon\"; rings: readonly (readonly number[])[] }\n/** A stroked circle: the points at distance innerRadius ≤ d ≤ outerRadius from the centre, mask units. */\nexport interface ChartMaskAnnulus { kind: \"annulus\"; centerX: number; centerY: number; innerRadius: number; outerRadius: number }\nexport type ChartMaskShape = ChartMaskPolygon | ChartMaskAnnulus;\n/** A shape mask printed over the chart: its box [0, unitsWidth] × [0, unitsHeight] (y down) fills `rectangle` (frame units, v up). */\nexport interface ChartMaskLayer {\n kind: \"shape-mask\";\n rectangle: { u0: number; v0: number; u1: number; v1: number };\n unitsWidth: number;\n unitsHeight: number;\n /** 1 to 4096 shapes, in order; the ink material where any contains the point. */\n shapes: readonly ChartMaskShape[];\n backgroundReflectance: ChartReflectance;\n inkReflectance: ChartReflectance;\n}\n/** A chart under 1 to 16 shape-mask layers, as data; `resolveChartMaterialLayers` evaluates it. */\nexport interface ChartMaterialLayerScene { kind: \"material-layers\"; sceneId: string; chart: ChartScene; layers: readonly ChartMaskLayer[] }\n\n/** The cell index grain of every layer: cells across and down the mask box. */\nexport const CHART_MASK_INDEX_GRAIN = /* @__PURE__ */ Object.freeze({ cellsX: 64, cellsY: 16 });\n/** Limits of a declared scene. */\nexport const CHART_MATERIAL_LAYER_LIMITS = /* @__PURE__ */ Object.freeze({ maximumLayers: 16, maximumShapes: 4096, maximumRings: 256, maximumEdges: 65_536 });\n\n/** Internal: a shape with its bounding box and flattened edges (polygon) or squared radii (annulus). */\nexport type ResolvedChartMaskShape =\n | { kind: \"polygon\"; box: readonly [number, number, number, number]; edges: Float64Array }\n | { kind: \"annulus\"; box: readonly [number, number, number, number]; centerX: number; centerY: number; inner2: number; outer2: number };\nexport interface ResolvedChartMaskLayer {\n rectangle: { u0: number; v0: number; u1: number; v1: number };\n unitsWidth: number;\n unitsHeight: number;\n /** Mask units per frame unit: unitsWidth / (u1 − u0) and unitsHeight / (v1 − v0). */\n scaleX: number;\n scaleY: number;\n shapes: readonly ResolvedChartMaskShape[];\n cellsX: number;\n cellsY: number;\n cellWidth: number;\n cellHeight: number;\n /** Per cell (row by row), the shape indices whose bounding box meets the cell grown by one cell. */\n cells: readonly Uint32Array[];\n backgroundMaterial: number;\n inkMaterial: number;\n /** Whether a point in mask units is ink (through the cell index). */\n containsUnits(x: number, y: number): boolean;\n}\nexport interface ResolvedChartMaterialLayers {\n kind: \"material-layers\";\n sceneId: string;\n /** The chart under the layers; its materials come first in `materials`. */\n chart: ResolvedChartScene;\n layers: readonly ResolvedChartMaskLayer[];\n materials: ResolvedChartScene[\"materials\"];\n /** Internal: the caller input behind each material (undefined for an engine neutral), for the scene digest. */\n materialInputs: readonly unknown[];\n /** Material index at a frame point (u right, v up): the topmost layer whose rectangle holds the point, else the chart. */\n materialAt(u: number, v: number): number;\n /** The same scene as a caller material scene for `simulateCapture` and the display view (chart-local coordinates when the chart has a size). */\n callerScene: CallerMaterialScene;\n}\n\nconst SCENE_ID = /^[A-Za-z0-9][A-Za-z0-9._:-]{0,63}$/u;\nconst finite = (value: unknown, name: string): number => {\n if (typeof value !== \"number\" || !Number.isFinite(value)) throw new InvalidConfigurationError(name + \" must be a finite number.\");\n return value;\n};\n/** The smallest cell the one-cell margin covers: the rounding of (x − 0)·scale is a few units in the last place of the coordinates. */\nconst minimumCell = (extent: number): number => Math.max(extent, Number.MIN_VALUE) * 2 ** -20;\n\nfunction resolvePolygon(shape: ChartMaskPolygon, name: string): ResolvedChartMaskShape {\n const rings = shape.rings;\n if (!Array.isArray(rings) || rings.length < 1 || rings.length > CHART_MATERIAL_LAYER_LIMITS.maximumRings) throw new InvalidConfigurationError(name + \" needs 1 to 256 rings.\");\n let count = 0;\n for (const ring of rings) {\n if (!Array.isArray(ring) || ring.length < 6 || ring.length % 2 !== 0) throw new InvalidConfigurationError(name + \" rings need at least three (x, y) vertices.\");\n count += ring.length / 2;\n }\n if (count > CHART_MATERIAL_LAYER_LIMITS.maximumEdges) throw new InvalidConfigurationError(name + \" has more than 65536 edges.\");\n const edges = new Float64Array(4 * count);\n let minX = Infinity, minY = Infinity, maxX = -Infinity, maxY = -Infinity, e = 0;\n for (const ring of rings) {\n const n = ring.length / 2;\n for (let k = 0; k < n; k++) {\n const x0 = finite(ring[2 * k], name + \" vertex\"), y0 = finite(ring[2 * k + 1], name + \" vertex\");\n const next = k + 1 === n ? 0 : k + 1, x1 = finite(ring[2 * next], name + \" vertex\"), y1 = finite(ring[2 * next + 1], name + \" vertex\");\n edges[e++] = x0; edges[e++] = y0; edges[e++] = x1; edges[e++] = y1;\n minX = Math.min(minX, x0); minY = Math.min(minY, y0); maxX = Math.max(maxX, x0); maxY = Math.max(maxY, y0);\n }\n }\n return { kind: \"polygon\", box: [minX, minY, maxX, maxY], edges };\n}\n\n/** Non-zero winding over the edges (x0, y0, x1, y1), as the reference evaluates it; the GPU runs the same comparisons. */\nexport function polygonWinding(edges: Float64Array, x: number, y: number): number {\n let winding = 0;\n for (let k = 0; k < edges.length; k += 4) {\n const x0 = edges[k]!, y0 = edges[k + 1]!, x1 = edges[k + 2]!, y1 = edges[k + 3]!;\n const side = (x1 - x0) * (y - y0) - (x - x0) * (y1 - y0);\n if (y0 <= y) {\n if (y1 > y && side > 0) winding++;\n } else if (y1 <= y && side < 0) winding--;\n }\n return winding;\n}\n/** Whether a resolved shape contains a point in mask units (the full test, without the cell index). */\nexport function shapeContains(shape: ResolvedChartMaskShape, x: number, y: number): boolean {\n const b = shape.box;\n if (!(x >= b[0] && x <= b[2] && y >= b[1] && y <= b[3])) return false;\n if (shape.kind === \"annulus\") {\n const d2 = (x - shape.centerX) * (x - shape.centerX) + (y - shape.centerY) * (y - shape.centerY);\n return d2 >= shape.inner2 && d2 <= shape.outer2;\n }\n return polygonWinding(shape.edges, x, y) !== 0;\n}\n\nfunction resolveLayer(value: unknown, name: string, aspect: number, materials: ResolvedChartScene[\"materials\"][number][], inputs: unknown[]): ResolvedChartMaskLayer {\n requireInputObject(value, name);\n const layer = value as Record<string, unknown>;\n for (const key of Object.keys(layer)) {\n if (![\"kind\", \"rectangle\", \"unitsWidth\", \"unitsHeight\", \"shapes\", \"backgroundReflectance\", \"inkReflectance\"].includes(key)) throw new InvalidConfigurationError(\"Unknown \" + name + \" field: \" + key + \".\");\n }\n if (layer.kind !== \"shape-mask\") throw new InvalidConfigurationError(name + \".kind must be shape-mask.\");\n requireInputObject(layer.rectangle, name + \".rectangle\");\n const r = layer.rectangle as Record<string, unknown>;\n for (const key of Object.keys(r)) if (![\"u0\", \"v0\", \"u1\", \"v1\"].includes(key)) throw new InvalidConfigurationError(\"Unknown \" + name + \".rectangle field: \" + key + \".\");\n const u0 = finite(r.u0, name + \".rectangle.u0\"), v0 = finite(r.v0, name + \".rectangle.v0\"), u1 = finite(r.u1, name + \".rectangle.u1\"), v1 = finite(r.v1, name + \".rectangle.v1\");\n if (!(u1 > u0 && v1 > v0) || Math.max(Math.abs(u0), Math.abs(u1)) > 1e6 || Math.max(Math.abs(v0), Math.abs(v1)) > 1e6 * Math.max(1, aspect)) {\n throw new InvalidConfigurationError(name + \".rectangle needs u0 < u1 and v0 < v1 within 10^6 frame units.\");\n }\n const unitsWidth = finite(layer.unitsWidth, name + \".unitsWidth\"), unitsHeight = finite(layer.unitsHeight, name + \".unitsHeight\");\n if (!(unitsWidth > 0 && unitsHeight > 0 && unitsWidth <= 1e9 && unitsHeight <= 1e9)) throw new InvalidConfigurationError(name + \" units must be positive and at most 10^9.\");\n const list = layer.shapes;\n if (!Array.isArray(list) || list.length < 1 || list.length > CHART_MATERIAL_LAYER_LIMITS.maximumShapes) throw new InvalidConfigurationError(name + \".shapes must list 1 to 4096 shapes.\");\n const shapes = list.map((shape: unknown, index: number): ResolvedChartMaskShape => {\n const label = name + \".shapes[\" + index + \"]\";\n requireInputObject(shape, label);\n const s = shape as Record<string, unknown>;\n if (s.kind === \"polygon\") {\n for (const key of Object.keys(s)) if (key !== \"kind\" && key !== \"rings\") throw new InvalidConfigurationError(\"Unknown \" + label + \" field: \" + key + \".\");\n return resolvePolygon(s as unknown as ChartMaskPolygon, label);\n }\n if (s.kind !== \"annulus\") throw new InvalidConfigurationError(label + \".kind must be polygon or annulus.\");\n for (const key of Object.keys(s)) if (![\"kind\", \"centerX\", \"centerY\", \"innerRadius\", \"outerRadius\"].includes(key)) throw new InvalidConfigurationError(\"Unknown \" + label + \" field: \" + key + \".\");\n const cx = finite(s.centerX, label + \".centerX\"), cy = finite(s.centerY, label + \".centerY\");\n const inner = finite(s.innerRadius, label + \".innerRadius\"), outer = finite(s.outerRadius, label + \".outerRadius\");\n if (!(inner >= 0 && outer > inner)) throw new InvalidConfigurationError(label + \" needs 0 ≤ innerRadius < outerRadius.\");\n return { kind: \"annulus\", box: [cx - outer, cy - outer, cx + outer, cy + outer], centerX: cx, centerY: cy, inner2: inner * inner, outer2: outer * outer };\n });\n for (const shape of shapes) {\n if (!shape.box.every((c) => Math.abs(c) <= 1e9)) throw new InvalidConfigurationError(name + \" shape coordinates must stay within 10^9 units.\");\n }\n const backgroundMaterial = materials.length;\n materials.push(resolveChartMaterial(layer.backgroundReflectance, name + \".backgroundReflectance\"));\n inputs.push(typeof layer.backgroundReflectance === \"number\" ? undefined : layer.backgroundReflectance);\n const inkMaterial = materials.length;\n materials.push(resolveChartMaterial(layer.inkReflectance, name + \".inkReflectance\"));\n inputs.push(typeof layer.inkReflectance === \"number\" ? undefined : layer.inkReflectance);\n // The cell index over the mask box; the grain must stay large against the coordinates' rounding (see the header).\n const { cellsX, cellsY } = CHART_MASK_INDEX_GRAIN, cellWidth = unitsWidth / cellsX, cellHeight = unitsHeight / cellsY;\n const extentX = Math.max(unitsWidth, ...shapes.map((s) => Math.max(Math.abs(s.box[0]), Math.abs(s.box[2]))));\n const extentY = Math.max(unitsHeight, ...shapes.map((s) => Math.max(Math.abs(s.box[1]), Math.abs(s.box[3]))));\n if (!(cellWidth > minimumCell(extentX) && cellHeight > minimumCell(extentY))) throw new InvalidConfigurationError(name + \": the shapes extend too far beyond the mask box for its cell index.\");\n const cells: Uint32Array[] = [];\n for (let j = 0; j < cellsY; j++) {\n for (let i = 0; i < cellsX; i++) {\n const x0 = (i - 1) * cellWidth, x1 = (i + 2) * cellWidth, y0 = (j - 1) * cellHeight, y1 = (j + 2) * cellHeight, listed: number[] = [];\n shapes.forEach((s, k) => { if (s.box[0] <= x1 && s.box[2] >= x0 && s.box[1] <= y1 && s.box[3] >= y0) listed.push(k); });\n cells.push(Uint32Array.from(listed));\n }\n }\n const scaleX = unitsWidth / (u1 - u0), scaleY = unitsHeight / (v1 - v0);\n return Object.freeze({ rectangle: Object.freeze({ u0, v0, u1, v1 }), unitsWidth, unitsHeight, scaleX, scaleY, shapes: Object.freeze(shapes), cellsX, cellsY, cellWidth, cellHeight,\n cells: Object.freeze(cells), backgroundMaterial, inkMaterial,\n containsUnits(x: number, y: number): boolean {\n let i = Math.floor(x / cellWidth), j = Math.floor(y / cellHeight);\n if (!(i > 0)) i = 0; else if (i >= cellsX) i = cellsX - 1;\n if (!(j > 0)) j = 0; else if (j >= cellsY) j = cellsY - 1;\n const list = cells[j * cellsX + i]!;\n for (let k = 0; k < list.length; k++) if (shapeContains(shapes[list[k]!]!, x, y)) return true;\n return false;\n } });\n}\n\n/**\n * Validates a declared material scene and resolves its chart (in a frame of `aspect` = height / width) and its\n * layers. `materialAt` is the float64 reference the GPU stage is checked against, and `callerScene` is the same\n * scene for `simulateCapture`'s `scene` option.\n */\nexport function resolveChartMaterialLayers(input: { scene: ChartMaterialLayerScene; aspect: number }): ResolvedChartMaterialLayers {\n requireInputKeys(input, \"resolveChartMaterialLayers\", [\"scene\", \"aspect\"]);\n const { scene, aspect } = input;\n requireInputObject(scene, \"scene\");\n const record = scene as unknown as Record<string, unknown>;\n for (const key of Object.keys(record)) if (![\"kind\", \"sceneId\", \"chart\", \"layers\"].includes(key)) throw new InvalidConfigurationError(\"Unknown scene field: \" + key + \".\");\n if (record.kind !== \"material-layers\") throw new InvalidConfigurationError(\"scene.kind must be material-layers.\");\n if (typeof record.sceneId !== \"string\" || !SCENE_ID.test(record.sceneId)) throw new InvalidConfigurationError(\"A material-layers scene needs a public sceneId.\");\n if (typeof aspect !== \"number\" || !Number.isFinite(aspect) || aspect <= 0) throw new InvalidConfigurationError(\"Chart aspect must be positive.\");\n const chart = resolveChartScene({ scene: record.chart as ChartScene, aspect });\n const list = record.layers;\n if (!Array.isArray(list) || list.length < 1 || list.length > CHART_MATERIAL_LAYER_LIMITS.maximumLayers) throw new InvalidConfigurationError(\"layers must list 1 to 16 shape-mask layers.\");\n const materials: ResolvedChartScene[\"materials\"][number][] = [...chart.materials], inputs: unknown[] = [...chartMaterialInputs(chart)];\n const layers = list.map((layer: unknown, index: number) => resolveLayer(layer, \"layers[\" + index + \"]\", aspect, materials, inputs));\n const materialAt = (u: number, v: number): number => {\n for (let l = layers.length - 1; l >= 0; l--) {\n const layer = layers[l]!, r = layer.rectangle;\n if (u < r.u0 || u > r.u1 || v < r.v0 || v > r.v1) continue;\n return layer.containsUnits((u - r.u0) * layer.scaleX, (r.v1 - v) * layer.scaleY) ? layer.inkMaterial : layer.backgroundMaterial;\n }\n return chart.materialAt(u, v);\n };\n const callerMaterials = materials.map((m, k) => (m.kind === \"neutral\" ? m.reflectance : inputs[k] as ChartReflectance));\n const callerScene: CallerMaterialScene = Object.freeze({ kind: \"material-function\" as const, sceneId: record.sceneId, materials: Object.freeze(callerMaterials),\n materialAt: (p: Readonly<SceneMaterialPoint>) => materialAt(p.chartU ?? p.u, p.chartV ?? p.v) });\n return Object.freeze({ kind: \"material-layers\" as const, sceneId: record.sceneId, chart, layers: Object.freeze(layers), materials: Object.freeze(materials),\n materialInputs: Object.freeze(inputs), materialAt, callerScene });\n}\n"]}
@@ -23,7 +23,7 @@ import { resolveChartMaterialLayers } from "./chart-material-layers.js";
23
23
  import { buildPlanarSceneRadianceProvider, calculateIlluminantIrradianceScale, resolveCaptureIlluminant, tabulatedSpectrum } from "./scene-radiance.js";
24
24
  export const CHART_RADIANCE_BATCH_SCHEMA_VERSION = "0.1.0";
25
25
  /** `maximumQueries` is the default batch limit; a request may raise it with its own `maximumQueries`, up to `ceilingQueries`. */
26
- export const CHART_RADIANCE_BATCH_LIMITS = Object.freeze({ maximumQueries: 24_000_000, ceilingQueries: FULL_RESOLUTION_CEILING_PIXELS, maximumWavelengths: 256,
26
+ export const CHART_RADIANCE_BATCH_LIMITS = /* @__PURE__ */ Object.freeze({ maximumQueries: 24_000_000, ceilingQueries: FULL_RESOLUTION_CEILING_PIXELS, maximumWavelengths: 256,
27
27
  maximumChannels: 4 });
28
28
  export function calculateChartRadianceBatchPlan(input) {
29
29
  const r = requireAllowlistedRecord(input, ["schemaVersion", "scene", "illuminant", "illuminanceLux", "aspect", "points", "wavelengthsNanometers",
@@ -1 +1 @@
1
- {"version":3,"file":"chart-radiance-batch.js","sourceRoot":"","sources":["../../src/facade/chart-radiance-batch.ts"],"names":[],"mappings":"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","sourcesContent":["// SPDX-License-Identifier: Apache-2.0\n\n/**\n * Batched radiance queries for the engine's procedural chart scenes (#277): many frame points in one\n * call, each answered with spectral radiance at a declared wavelength, or with the spectral integral of\n * that radiance against declared channel weights. This is the float64 CPU reference for the\n * `webgpu-f32` chart-radiance stage (`ImageKernelAccelerator.evaluateChartRadiance`).\n *\n * Every value comes from the chart provider's own `radianceAt` (createPlanarSceneRadianceProvider): a\n * Lambertian reflectance ρ(λ) under the scaled illuminant, L = ρ·k·S(λ)/π. The spectral integral of a\n * query is Σ_j w_cj·L(u, v, λ_j), summed in wavelength order. Charts are uniform-illuminant Lambertian\n * patterns, so a query's integral depends only on its material: the GPU stage uses exactly that.\n *\n * The query shape mirrors a batched provider (one call, queries in, results in the same order). Points\n * are frame units (u right, v up; see chart-scenes.ts); `mapEnvironmentDirectionsToChartPoints` converts\n * environment-direction queries exactly as `evaluateRadiance` does.\n * @see docs/WEBGPU.md, \"Scene radiance on the GPU\".\n */\n\nimport { InvalidConfigurationError } from \"../core/configuration-error.js\";\nimport { requireAllowlistedRecord } from \"../core/record-validation.js\";\nimport { FULL_RESOLUTION_CEILING_PIXELS, resolveRaisedLimit } from \"../core/pixel-limits.js\";\nimport { resolveChartScene, type ChartScene, type ResolvedChartScene } from \"./chart-scenes.js\";\nimport { resolveChartMaterialLayers, type ChartMaterialLayerScene, type ResolvedChartMaterialLayers } from \"./chart-material-layers.js\";\nimport { buildPlanarSceneRadianceProvider, calculateIlluminantIrradianceScale, resolveCaptureIlluminant, tabulatedSpectrum, type CaptureIlluminant,\n type ResolvedCaptureIlluminant } from \"./scene-radiance.js\";\n\nexport const CHART_RADIANCE_BATCH_SCHEMA_VERSION = \"0.1.0\" as const;\n/** `maximumQueries` is the default batch limit; a request may raise it with its own `maximumQueries`, up to `ceilingQueries`. */\nexport const CHART_RADIANCE_BATCH_LIMITS = Object.freeze({ maximumQueries: 24_000_000, ceilingQueries: FULL_RESOLUTION_CEILING_PIXELS, maximumWavelengths: 256,\n maximumChannels: 4 });\n\nexport interface ChartRadianceBatchInput {\n schemaVersion: typeof CHART_RADIANCE_BATCH_SCHEMA_VERSION;\n /** An engine chart preset, or (#477) a declared `material-layers` scene: a chart under shape-mask layers. Caller scene functions are not supported here. */\n scene: ChartScene | ChartMaterialLayerScene;\n illuminant: CaptureIlluminant;\n illuminanceLux: number;\n /** Frame height / width. */\n aspect: number;\n /** Frame points, interleaved [u0, v0, u1, v1, …]. Finite. */\n points: Float32Array | Float64Array;\n /** The wavelengths the queries use, in nanometres (1–256). */\n wavelengthsNanometers: readonly number[];\n /** Radiance queries: one wavelength index per point. Exactly one of this and `channelWeights`. */\n wavelengthIndices?: Uint8Array | Uint16Array;\n /** Spectral integration: per channel (1–4), one finite weight per wavelength. */\n channelWeights?: readonly (readonly number[])[];\n /**\n * Optional opt-in batch limit: an integer from 1 to `CHART_RADIANCE_BATCH_LIMITS.ceilingQueries`. Default\n * `CHART_RADIANCE_BATCH_LIMITS.maximumQueries` (24 000 000). It does not change the values.\n */\n maximumQueries?: number;\n}\n\n/** Validated plan with the resolved chart, illuminant and irradiance scale. Arrays are borrowed. */\nexport interface ChartRadianceBatchPlan {\n /** The resolved chart; with a `material-layers` scene, the chart under the layers. */\n chart: ResolvedChartScene;\n /** The resolved layers of a `material-layers` scene, or null for a chart preset. */\n layers: ResolvedChartMaterialLayers | null;\n /** Every material a query can resolve to: the chart's, then each layer's background and ink. */\n materials: ResolvedChartScene[\"materials\"];\n illuminant: ResolvedCaptureIlluminant;\n irradianceScale: number;\n queryCount: number;\n /** Output values per query: 1 for radiance queries, the channel count for spectral integration. */\n columns: number;\n mode: \"radiance\" | \"spectral-integral\";\n wavelengthsNanometers: readonly number[];\n channelWeights: readonly (readonly number[])[] | null;\n /** Spectral radiance of one material at a wavelength: the provider's own radianceAt for that material. */\n materialRadiance(material: number, wavelengthNanometers: number): number;\n /** The reference value of one query and output column (radianceAt, and its wavelength-ordered sum). */\n queryValue(points: Float32Array | Float64Array, wavelengthIndices: Uint8Array | Uint16Array | undefined, query: number, column: number): number;\n}\n\nexport function calculateChartRadianceBatchPlan(input: ChartRadianceBatchInput): ChartRadianceBatchPlan {\n const r = requireAllowlistedRecord(input, [\"schemaVersion\", \"scene\", \"illuminant\", \"illuminanceLux\", \"aspect\", \"points\", \"wavelengthsNanometers\",\n \"wavelengthIndices\", \"channelWeights\", \"maximumQueries\"], \"Invalid chart radiance batch input.\");\n if (r.schemaVersion !== CHART_RADIANCE_BATCH_SCHEMA_VERSION) throw new InvalidConfigurationError(\"Unsupported chart radiance batch schema.\");\n if (typeof r.aspect !== \"number\" || !(r.aspect > 0 && r.aspect <= Number.MAX_VALUE)) throw new InvalidConfigurationError(\"aspect must be positive.\");\n const sceneRecord = r.scene as Record<string, unknown> | null;\n const layers = sceneRecord !== null && typeof sceneRecord === \"object\" && sceneRecord.kind === \"material-layers\"\n ? resolveChartMaterialLayers({ scene: r.scene as ChartMaterialLayerScene, aspect: r.aspect }) : null;\n const chart = layers ? layers.chart : resolveChartScene({ scene: r.scene as ChartScene, aspect: r.aspect });\n const materials = layers ? layers.materials : chart.materials;\n const illuminant = resolveCaptureIlluminant(r.illuminant as CaptureIlluminant);\n const irradianceScale = calculateIlluminantIrradianceScale(illuminant.shape, r.illuminanceLux as number);\n const L = CHART_RADIANCE_BATCH_LIMITS, points = r.points;\n const maximumQueries = resolveRaisedLimit(r.maximumQueries, L.maximumQueries, L.ceilingQueries,\n \"Chart radiance batch maximumQueries must be an integer from 1 to \" + L.ceilingQueries + \".\");\n if (!(points instanceof Float32Array || points instanceof Float64Array) || points.length % 2 !== 0 || points.length / 2 > maximumQueries) {\n throw new InvalidConfigurationError(\"points must be an interleaved Float32Array or Float64Array of (u, v) pairs.\");\n }\n for (let i = 0; i < points.length; i++) if (!Number.isFinite(points[i]!)) throw new InvalidConfigurationError(\"Chart points must be finite.\");\n const queryCount = points.length / 2, wavelengths = r.wavelengthsNanometers;\n if (!Array.isArray(wavelengths) || wavelengths.length < 1 || wavelengths.length > L.maximumWavelengths ||\n wavelengths.some(nm => typeof nm !== \"number\" || !Number.isFinite(nm) || nm <= 0)) {\n throw new InvalidConfigurationError(\"wavelengthsNanometers must list 1 to 256 positive wavelengths.\");\n }\n const indices = r.wavelengthIndices, weights = r.channelWeights;\n if ((indices === undefined) === (weights === undefined)) throw new InvalidConfigurationError(\"Give exactly one of wavelengthIndices and channelWeights.\");\n if (indices !== undefined) {\n if (!(indices instanceof Uint8Array || indices instanceof Uint16Array) || indices.length !== queryCount) {\n throw new InvalidConfigurationError(\"wavelengthIndices must hold one index per point.\");\n }\n for (let i = 0; i < queryCount; i++) if (indices[i]! >= wavelengths.length) throw new InvalidConfigurationError(\"A wavelength index is out of range.\");\n } else if (!Array.isArray(weights) || weights.length < 1 || weights.length > L.maximumChannels ||\n weights.some(row => !Array.isArray(row) || row.length !== wavelengths.length || row.some(w => typeof w !== \"number\" || !Number.isFinite(w)))) {\n throw new InvalidConfigurationError(\"channelWeights must hold 1 to 4 rows of one finite weight per wavelength.\");\n }\n // The provider's own radiance function: chart reflectance × scaled illuminant / π, in its float64 order.\n const providerScene = layers ? { kind: \"material-function\" as const, sceneId: layers.sceneId, materials: layers.materials, materialInputs: layers.materialInputs,\n materialAt: (point: { u: number; v: number }): number => layers.materialAt(point.u, point.v) } : chart;\n const provider = buildPlanarSceneRadianceProvider({ scene: providerScene, sceneId: \"chart-radiance-batch\", providerProfileId: \"chart-radiance-batch\", illuminant,\n irradianceScale, geometry: { distanceM: 1, metresPerFrameUnit: 1 }, evidence: [], limitations: [] });\n const channelWeights = weights === undefined ? null : (weights as number[][]).map(row => Object.freeze([...row]));\n const nm = Object.freeze([...(wavelengths as number[])]);\n const shapeAt = tabulatedSpectrum(illuminant.shape);\n const materialRadiance = (material: number, wavelength: number): number => {\n const m = materials[material]!;\n const reflectance = m.kind === \"neutral\" ? m.reflectance : m.spectrum.evaluate(wavelength);\n if (m.kind === \"spectrum\" && !(reflectance >= 0 && reflectance <= 1)) throw new InvalidConfigurationError(\"Chart reflectance spectrum left [0, 1].\");\n return reflectance * irradianceScale * shapeAt(wavelength) / Math.PI;\n };\n return Object.freeze({ chart, layers, materials, illuminant, irradianceScale, queryCount, columns: channelWeights === null ? 1 : channelWeights.length,\n mode: channelWeights === null ? \"radiance\" as const : \"spectral-integral\" as const, wavelengthsNanometers: nm, channelWeights, materialRadiance,\n queryValue(p: Float32Array | Float64Array, w: Uint8Array | Uint16Array | undefined, query: number, column: number): number {\n const u = p[2 * query]!, v = p[2 * query + 1]!;\n if (channelWeights === null) return provider.radianceAt(u, v, nm[w![query]!]!);\n let sum = 0;\n const row = channelWeights[column]!;\n for (let j = 0; j < nm.length; j++) sum += row[j]! * provider.radianceAt(u, v, nm[j]!);\n return sum;\n } });\n}\n\n/** Float64 CPU reference: every query's value(s), row-major (query, column). */\nexport function calculateChartRadianceBatch(input: ChartRadianceBatchInput): { plan: ChartRadianceBatchPlan; values: Float64Array } {\n const plan = calculateChartRadianceBatchPlan(input), values = new Float64Array(plan.queryCount * plan.columns);\n for (let q = 0; q < plan.queryCount; q++) for (let c = 0; c < plan.columns; c++) values[q * plan.columns + c] = plan.queryValue(input.points, input.wavelengthIndices, q, c);\n return { plan, values };\n}\n\n/**\n * Frame points of environment-direction queries on the chart plane, exactly as the planar provider's\n * `evaluateRadiance` computes them: look direction l = −o, plane point l·distance/l.z, in frame units.\n * @param directions - Outgoing unit vectors (scene toward camera), interleaved [x, y, z, …].\n */\nexport function mapEnvironmentDirectionsToChartPoints(input: { directions: Float32Array | Float64Array; distanceM: number; metresPerFrameUnit: number }): Float64Array {\n const r = requireAllowlistedRecord(input, [\"directions\", \"distanceM\", \"metresPerFrameUnit\"], \"Invalid planar direction input.\");\n const d = r.directions, distance = r.distanceM, scale = r.metresPerFrameUnit;\n if (!(d instanceof Float32Array || d instanceof Float64Array) || d.length % 3 !== 0 || typeof distance !== \"number\" || !(distance > 0 && distance <= Number.MAX_VALUE) ||\n typeof scale !== \"number\" || !(scale > 0 && scale <= Number.MAX_VALUE)) {\n throw new InvalidConfigurationError(\"Planar directions need interleaved unit vectors, a positive distance and a positive frame scale.\");\n }\n const points = new Float64Array(d.length / 3 * 2);\n for (let i = 0; i < d.length / 3; i++) {\n const lz = -d[3 * i + 2]!;\n if (!(lz > 0)) throw new InvalidConfigurationError(\"Planar scene query does not point toward the scene plane.\");\n const t = distance / lz;\n const x = -d[3 * i]! * t / scale, y = -d[3 * i + 1]! * t / scale;\n // A grazing direction (lz near 0, e.g. 1e-320) or a non-finite component would give ±Infinity or NaN.\n if (!Number.isFinite(x) || !Number.isFinite(y)) throw new InvalidConfigurationError(\"Planar scene query maps to a non-finite chart point (grazing or non-finite direction).\");\n points[2 * i] = x;\n points[2 * i + 1] = y;\n }\n return points;\n}\n"]}
1
+ {"version":3,"file":"chart-radiance-batch.js","sourceRoot":"","sources":["../../src/facade/chart-radiance-batch.ts"],"names":[],"mappings":"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","sourcesContent":["// SPDX-License-Identifier: Apache-2.0\n\n/**\n * Batched radiance queries for the engine's procedural chart scenes (#277): many frame points in one\n * call, each answered with spectral radiance at a declared wavelength, or with the spectral integral of\n * that radiance against declared channel weights. This is the float64 CPU reference for the\n * `webgpu-f32` chart-radiance stage (`ImageKernelAccelerator.evaluateChartRadiance`).\n *\n * Every value comes from the chart provider's own `radianceAt` (createPlanarSceneRadianceProvider): a\n * Lambertian reflectance ρ(λ) under the scaled illuminant, L = ρ·k·S(λ)/π. The spectral integral of a\n * query is Σ_j w_cj·L(u, v, λ_j), summed in wavelength order. Charts are uniform-illuminant Lambertian\n * patterns, so a query's integral depends only on its material: the GPU stage uses exactly that.\n *\n * The query shape mirrors a batched provider (one call, queries in, results in the same order). Points\n * are frame units (u right, v up; see chart-scenes.ts); `mapEnvironmentDirectionsToChartPoints` converts\n * environment-direction queries exactly as `evaluateRadiance` does.\n * @see docs/WEBGPU.md, \"Scene radiance on the GPU\".\n */\n\nimport { InvalidConfigurationError } from \"../core/configuration-error.js\";\nimport { requireAllowlistedRecord } from \"../core/record-validation.js\";\nimport { FULL_RESOLUTION_CEILING_PIXELS, resolveRaisedLimit } from \"../core/pixel-limits.js\";\nimport { resolveChartScene, type ChartScene, type ResolvedChartScene } from \"./chart-scenes.js\";\nimport { resolveChartMaterialLayers, type ChartMaterialLayerScene, type ResolvedChartMaterialLayers } from \"./chart-material-layers.js\";\nimport { buildPlanarSceneRadianceProvider, calculateIlluminantIrradianceScale, resolveCaptureIlluminant, tabulatedSpectrum, type CaptureIlluminant,\n type ResolvedCaptureIlluminant } from \"./scene-radiance.js\";\n\nexport const CHART_RADIANCE_BATCH_SCHEMA_VERSION = \"0.1.0\" as const;\n/** `maximumQueries` is the default batch limit; a request may raise it with its own `maximumQueries`, up to `ceilingQueries`. */\nexport const CHART_RADIANCE_BATCH_LIMITS = /* @__PURE__ */ Object.freeze({ maximumQueries: 24_000_000, ceilingQueries: FULL_RESOLUTION_CEILING_PIXELS, maximumWavelengths: 256,\n maximumChannels: 4 });\n\nexport interface ChartRadianceBatchInput {\n schemaVersion: typeof CHART_RADIANCE_BATCH_SCHEMA_VERSION;\n /** An engine chart preset, or (#477) a declared `material-layers` scene: a chart under shape-mask layers. Caller scene functions are not supported here. */\n scene: ChartScene | ChartMaterialLayerScene;\n illuminant: CaptureIlluminant;\n illuminanceLux: number;\n /** Frame height / width. */\n aspect: number;\n /** Frame points, interleaved [u0, v0, u1, v1, …]. Finite. */\n points: Float32Array | Float64Array;\n /** The wavelengths the queries use, in nanometres (1–256). */\n wavelengthsNanometers: readonly number[];\n /** Radiance queries: one wavelength index per point. Exactly one of this and `channelWeights`. */\n wavelengthIndices?: Uint8Array | Uint16Array;\n /** Spectral integration: per channel (1–4), one finite weight per wavelength. */\n channelWeights?: readonly (readonly number[])[];\n /**\n * Optional opt-in batch limit: an integer from 1 to `CHART_RADIANCE_BATCH_LIMITS.ceilingQueries`. Default\n * `CHART_RADIANCE_BATCH_LIMITS.maximumQueries` (24 000 000). It does not change the values.\n */\n maximumQueries?: number;\n}\n\n/** Validated plan with the resolved chart, illuminant and irradiance scale. Arrays are borrowed. */\nexport interface ChartRadianceBatchPlan {\n /** The resolved chart; with a `material-layers` scene, the chart under the layers. */\n chart: ResolvedChartScene;\n /** The resolved layers of a `material-layers` scene, or null for a chart preset. */\n layers: ResolvedChartMaterialLayers | null;\n /** Every material a query can resolve to: the chart's, then each layer's background and ink. */\n materials: ResolvedChartScene[\"materials\"];\n illuminant: ResolvedCaptureIlluminant;\n irradianceScale: number;\n queryCount: number;\n /** Output values per query: 1 for radiance queries, the channel count for spectral integration. */\n columns: number;\n mode: \"radiance\" | \"spectral-integral\";\n wavelengthsNanometers: readonly number[];\n channelWeights: readonly (readonly number[])[] | null;\n /** Spectral radiance of one material at a wavelength: the provider's own radianceAt for that material. */\n materialRadiance(material: number, wavelengthNanometers: number): number;\n /** The reference value of one query and output column (radianceAt, and its wavelength-ordered sum). */\n queryValue(points: Float32Array | Float64Array, wavelengthIndices: Uint8Array | Uint16Array | undefined, query: number, column: number): number;\n}\n\nexport function calculateChartRadianceBatchPlan(input: ChartRadianceBatchInput): ChartRadianceBatchPlan {\n const r = requireAllowlistedRecord(input, [\"schemaVersion\", \"scene\", \"illuminant\", \"illuminanceLux\", \"aspect\", \"points\", \"wavelengthsNanometers\",\n \"wavelengthIndices\", \"channelWeights\", \"maximumQueries\"], \"Invalid chart radiance batch input.\");\n if (r.schemaVersion !== CHART_RADIANCE_BATCH_SCHEMA_VERSION) throw new InvalidConfigurationError(\"Unsupported chart radiance batch schema.\");\n if (typeof r.aspect !== \"number\" || !(r.aspect > 0 && r.aspect <= Number.MAX_VALUE)) throw new InvalidConfigurationError(\"aspect must be positive.\");\n const sceneRecord = r.scene as Record<string, unknown> | null;\n const layers = sceneRecord !== null && typeof sceneRecord === \"object\" && sceneRecord.kind === \"material-layers\"\n ? resolveChartMaterialLayers({ scene: r.scene as ChartMaterialLayerScene, aspect: r.aspect }) : null;\n const chart = layers ? layers.chart : resolveChartScene({ scene: r.scene as ChartScene, aspect: r.aspect });\n const materials = layers ? layers.materials : chart.materials;\n const illuminant = resolveCaptureIlluminant(r.illuminant as CaptureIlluminant);\n const irradianceScale = calculateIlluminantIrradianceScale(illuminant.shape, r.illuminanceLux as number);\n const L = CHART_RADIANCE_BATCH_LIMITS, points = r.points;\n const maximumQueries = resolveRaisedLimit(r.maximumQueries, L.maximumQueries, L.ceilingQueries,\n \"Chart radiance batch maximumQueries must be an integer from 1 to \" + L.ceilingQueries + \".\");\n if (!(points instanceof Float32Array || points instanceof Float64Array) || points.length % 2 !== 0 || points.length / 2 > maximumQueries) {\n throw new InvalidConfigurationError(\"points must be an interleaved Float32Array or Float64Array of (u, v) pairs.\");\n }\n for (let i = 0; i < points.length; i++) if (!Number.isFinite(points[i]!)) throw new InvalidConfigurationError(\"Chart points must be finite.\");\n const queryCount = points.length / 2, wavelengths = r.wavelengthsNanometers;\n if (!Array.isArray(wavelengths) || wavelengths.length < 1 || wavelengths.length > L.maximumWavelengths ||\n wavelengths.some(nm => typeof nm !== \"number\" || !Number.isFinite(nm) || nm <= 0)) {\n throw new InvalidConfigurationError(\"wavelengthsNanometers must list 1 to 256 positive wavelengths.\");\n }\n const indices = r.wavelengthIndices, weights = r.channelWeights;\n if ((indices === undefined) === (weights === undefined)) throw new InvalidConfigurationError(\"Give exactly one of wavelengthIndices and channelWeights.\");\n if (indices !== undefined) {\n if (!(indices instanceof Uint8Array || indices instanceof Uint16Array) || indices.length !== queryCount) {\n throw new InvalidConfigurationError(\"wavelengthIndices must hold one index per point.\");\n }\n for (let i = 0; i < queryCount; i++) if (indices[i]! >= wavelengths.length) throw new InvalidConfigurationError(\"A wavelength index is out of range.\");\n } else if (!Array.isArray(weights) || weights.length < 1 || weights.length > L.maximumChannels ||\n weights.some(row => !Array.isArray(row) || row.length !== wavelengths.length || row.some(w => typeof w !== \"number\" || !Number.isFinite(w)))) {\n throw new InvalidConfigurationError(\"channelWeights must hold 1 to 4 rows of one finite weight per wavelength.\");\n }\n // The provider's own radiance function: chart reflectance × scaled illuminant / π, in its float64 order.\n const providerScene = layers ? { kind: \"material-function\" as const, sceneId: layers.sceneId, materials: layers.materials, materialInputs: layers.materialInputs,\n materialAt: (point: { u: number; v: number }): number => layers.materialAt(point.u, point.v) } : chart;\n const provider = buildPlanarSceneRadianceProvider({ scene: providerScene, sceneId: \"chart-radiance-batch\", providerProfileId: \"chart-radiance-batch\", illuminant,\n irradianceScale, geometry: { distanceM: 1, metresPerFrameUnit: 1 }, evidence: [], limitations: [] });\n const channelWeights = weights === undefined ? null : (weights as number[][]).map(row => Object.freeze([...row]));\n const nm = Object.freeze([...(wavelengths as number[])]);\n const shapeAt = tabulatedSpectrum(illuminant.shape);\n const materialRadiance = (material: number, wavelength: number): number => {\n const m = materials[material]!;\n const reflectance = m.kind === \"neutral\" ? m.reflectance : m.spectrum.evaluate(wavelength);\n if (m.kind === \"spectrum\" && !(reflectance >= 0 && reflectance <= 1)) throw new InvalidConfigurationError(\"Chart reflectance spectrum left [0, 1].\");\n return reflectance * irradianceScale * shapeAt(wavelength) / Math.PI;\n };\n return Object.freeze({ chart, layers, materials, illuminant, irradianceScale, queryCount, columns: channelWeights === null ? 1 : channelWeights.length,\n mode: channelWeights === null ? \"radiance\" as const : \"spectral-integral\" as const, wavelengthsNanometers: nm, channelWeights, materialRadiance,\n queryValue(p: Float32Array | Float64Array, w: Uint8Array | Uint16Array | undefined, query: number, column: number): number {\n const u = p[2 * query]!, v = p[2 * query + 1]!;\n if (channelWeights === null) return provider.radianceAt(u, v, nm[w![query]!]!);\n let sum = 0;\n const row = channelWeights[column]!;\n for (let j = 0; j < nm.length; j++) sum += row[j]! * provider.radianceAt(u, v, nm[j]!);\n return sum;\n } });\n}\n\n/** Float64 CPU reference: every query's value(s), row-major (query, column). */\nexport function calculateChartRadianceBatch(input: ChartRadianceBatchInput): { plan: ChartRadianceBatchPlan; values: Float64Array } {\n const plan = calculateChartRadianceBatchPlan(input), values = new Float64Array(plan.queryCount * plan.columns);\n for (let q = 0; q < plan.queryCount; q++) for (let c = 0; c < plan.columns; c++) values[q * plan.columns + c] = plan.queryValue(input.points, input.wavelengthIndices, q, c);\n return { plan, values };\n}\n\n/**\n * Frame points of environment-direction queries on the chart plane, exactly as the planar provider's\n * `evaluateRadiance` computes them: look direction l = −o, plane point l·distance/l.z, in frame units.\n * @param directions - Outgoing unit vectors (scene toward camera), interleaved [x, y, z, …].\n */\nexport function mapEnvironmentDirectionsToChartPoints(input: { directions: Float32Array | Float64Array; distanceM: number; metresPerFrameUnit: number }): Float64Array {\n const r = requireAllowlistedRecord(input, [\"directions\", \"distanceM\", \"metresPerFrameUnit\"], \"Invalid planar direction input.\");\n const d = r.directions, distance = r.distanceM, scale = r.metresPerFrameUnit;\n if (!(d instanceof Float32Array || d instanceof Float64Array) || d.length % 3 !== 0 || typeof distance !== \"number\" || !(distance > 0 && distance <= Number.MAX_VALUE) ||\n typeof scale !== \"number\" || !(scale > 0 && scale <= Number.MAX_VALUE)) {\n throw new InvalidConfigurationError(\"Planar directions need interleaved unit vectors, a positive distance and a positive frame scale.\");\n }\n const points = new Float64Array(d.length / 3 * 2);\n for (let i = 0; i < d.length / 3; i++) {\n const lz = -d[3 * i + 2]!;\n if (!(lz > 0)) throw new InvalidConfigurationError(\"Planar scene query does not point toward the scene plane.\");\n const t = distance / lz;\n const x = -d[3 * i]! * t / scale, y = -d[3 * i + 1]! * t / scale;\n // A grazing direction (lz near 0, e.g. 1e-320) or a non-finite component would give ±Infinity or NaN.\n if (!Number.isFinite(x) || !Number.isFinite(y)) throw new InvalidConfigurationError(\"Planar scene query maps to a non-finite chart point (grazing or non-finite direction).\");\n points[2 * i] = x;\n points[2 * i + 1] = y;\n }\n return points;\n}\n"]}
@@ -1,6 +1,18 @@
1
1
  import { type ColorimetricSpectrum, type PreparedColorimetricSpectrum } from "../color/color-matching-functions.js";
2
- /** A neutral (spectrally flat) reflectance in [0, 1], or a caller reflectance spectrum (values in [0, 1]). */
3
- export type ChartReflectance = number | ColorimetricSpectrum;
2
+ import { type ColorPatchId } from "./color-patches.js";
3
+ /**
4
+ * 2.14: one of the engine's built-in color patches (see `getColorPatchSet()`): its reflectance spectrum, Photivra's own
5
+ * analytic design, rendered through the same spectral path as a caller spectrum.
6
+ */
7
+ export interface ColorPatchReflectance {
8
+ kind: "color-patch";
9
+ patchId: ColorPatchId;
10
+ }
11
+ /**
12
+ * A neutral (spectrally flat) reflectance in [0, 1], a caller reflectance spectrum (values in [0, 1]) or, from 2.14, a
13
+ * built-in color patch `{ kind: "color-patch", patchId }`.
14
+ */
15
+ export type ChartReflectance = number | ColorimetricSpectrum | ColorPatchReflectance;
4
16
  export interface UniformChartScene {
5
17
  preset: "uniform";
6
18
  reflectance?: ChartReflectance;
@@ -66,7 +78,7 @@ export interface PointGridChartScene {
66
78
  }
67
79
  export interface PatchChartScene {
68
80
  preset: "patches";
69
- /** Caller reflectance per patch, row-major; the facade bundles no colour-chart data. 1..1024 patches. */
81
+ /** Caller reflectance per patch, row-major; the facade bundles no color-chart data. 1..1024 patches. */
70
82
  patches: readonly {
71
83
  patchId: string;
72
84
  reflectance: ChartReflectance;
@@ -77,6 +89,22 @@ export interface PatchChartScene {
77
89
  gapFraction?: number;
78
90
  backgroundReflectance?: number;
79
91
  }
92
+ /**
93
+ * 2.14: the built-in Photivra color patches (`getColorPatchSet()`) in a grid, drawn like `patches`: row-major, each
94
+ * patch centred in an equal cell with a neutral gap around it. The spectra are the engine's own analytic designs; no
95
+ * third-party chart data, names, order or layout are used.
96
+ */
97
+ export interface ColorPatchesChartScene {
98
+ preset: "color-patches";
99
+ /** Patches to draw, row-major, distinct. Default: the whole set in `COLOR_PATCH_IDS` order (30 patches, six per row). */
100
+ patchIds?: readonly ColorPatchId[];
101
+ /** Patches per row, 1 to the patch count. Default min(6, patch count). */
102
+ columns?: number;
103
+ /** Gap between patches as a fraction of the cell size, [0, 0.5). Default 0.1. */
104
+ gapFraction?: number;
105
+ /** Neutral reflectance of the gaps and empty cells. Default 0.18. */
106
+ backgroundReflectance?: number;
107
+ }
80
108
  /**
81
109
  * 2.3: seeded dead-leaves texture (Matheron's random closed set model, in the scale-invariant form used for
82
110
  * camera texture measurement by Cao, Guichard and Hornung): opaque disks with Poisson-distributed centres,
@@ -186,7 +214,7 @@ export interface FiducialChartScene {
186
214
  backgroundReflectance?: number;
187
215
  }
188
216
  /** Any chart preset except `composite`: a composite's background or element. */
189
- export type ChartElementScene = UniformChartScene | SlantedEdgeChartScene | SiemensStarChartScene | StepWedgeChartScene | GreyRampChartScene | CheckerboardChartScene | PointGridChartScene | PatchChartScene | DeadLeavesChartScene | BarGroupsChartScene | HyperbolicWedgeChartScene | ZonePlateChartScene | SlantedSquaresChartScene | LineGridChartScene | FiducialChartScene;
217
+ export type ChartElementScene = UniformChartScene | SlantedEdgeChartScene | SiemensStarChartScene | StepWedgeChartScene | GreyRampChartScene | CheckerboardChartScene | PointGridChartScene | PatchChartScene | ColorPatchesChartScene | DeadLeavesChartScene | BarGroupsChartScene | HyperbolicWedgeChartScene | ZonePlateChartScene | SlantedSquaresChartScene | LineGridChartScene | FiducialChartScene;
190
218
  /**
191
219
  * One element of a composite chart: a preset drawn inside its placement rectangle (frame units of the
192
220
  * composite). The element sees its own frame: u = ±1 at the rectangle's left and right edges, aspect =
@@ -310,6 +338,11 @@ export declare const CHART_SCENE_DEFAULTS: Readonly<{
310
338
  lightReflectance: 0.8;
311
339
  backgroundReflectance: 0.18;
312
340
  }>;
341
+ "color-patches": Readonly<{
342
+ patchIds: readonly ["neutral-1", "neutral-2", "neutral-3", "neutral-4", "neutral-5", "neutral-6", "red", "yellow", "green", "cyan", "blue", "magenta", "red-soft", "yellow-soft", "green-soft", "cyan-soft", "blue-soft", "magenta-soft", "skin-pale", "skin-medium", "skin-tan", "skin-deep", "sky-blue", "foliage-green", "brick-red", "sand", "teal", "lavender", "deep-orange", "deep-violet"];
343
+ gapFraction: 0.1;
344
+ backgroundReflectance: 0.18;
345
+ }>;
313
346
  composite: Readonly<{
314
347
  background: Readonly<{
315
348
  preset: "uniform";
@@ -348,8 +381,11 @@ export declare const CHART_SPECTRAL_RANGE_NANOMETERS: Readonly<{
348
381
  minimum: 380;
349
382
  maximum: 780;
350
383
  }>;
351
- /** Internal: validates a chart reflectance input (a neutral number or a reflectance spectrum covering 380–780 nm) as a material. */
352
- export declare function resolveChartMaterial(value: unknown, name: string): ResolvedChartScene["materials"][number];
384
+ /**
385
+ * Internal: validates a chart reflectance input (a neutral number, a reflectance spectrum covering 380–780 nm or a
386
+ * built-in color patch) as a material.
387
+ */
388
+ export declare function resolveChartMaterial(value: unknown, name: string, exp?: (x: number) => number): ResolvedChartScene["materials"][number];
353
389
  /**
354
390
  * Internal (not exported from the package): the caller input behind each material of a resolved chart, in
355
391
  * material order (`undefined` for an engine neutral). The facade hashes caller spectra from these inputs.
@@ -494,8 +530,9 @@ export declare function resolveChartScene(input: {
494
530
  }): ResolvedChartScene;
495
531
  /**
496
532
  * Internal (not exported from the package): {@link resolveChartScene} with the step wedge's geometric levels computed
497
- * with the portable power (`portablePow`, within 1 ulp) instead of `**`, whose last bit differs between JavaScript
498
- * engines. Every other value, the geometry and the material order are the same. The display view uses its materials.
533
+ * with the portable power (`portablePow`, within 1 ulp) instead of `**`, and (2.14) the built-in color patches with the
534
+ * portable exponential (`portableExp`) instead of `Math.exp`, whose last bits differ between JavaScript engines. Every
535
+ * other value, the geometry and the material order are the same. The display view uses its materials.
499
536
  */
500
537
  export declare function resolvePortableChartScene(input: {
501
538
  scene: ChartScene;