@photivra/engine 2.2.1 → 2.3.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 +16 -1
- package/CITATION.cff +1 -1
- package/README.md +6 -6
- package/SECURITY.md +1 -1
- package/dist/capture/native-environment-raw.d.ts +18 -0
- package/dist/capture/native-environment-raw.js +17 -1
- package/dist/capture/native-environment-raw.js.map +1 -1
- package/dist/capture/native-raw.d.ts +3 -0
- package/dist/capture/native-raw.js +8 -5
- package/dist/capture/native-raw.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/generic-prime-lenses.d.ts +46 -0
- package/dist/equipment/generic-prime-lenses.js +59 -0
- package/dist/equipment/generic-prime-lenses.js.map +1 -0
- package/dist/facade/chart-scenes.d.ts +270 -1
- package/dist/facade/chart-scenes.js +443 -17
- package/dist/facade/chart-scenes.js.map +1 -1
- package/dist/facade/scene-radiance.d.ts +47 -0
- package/dist/facade/scene-radiance.js +65 -5
- package/dist/facade/scene-radiance.js.map +1 -1
- package/dist/facade/simulate-capture.d.ts +151 -4
- package/dist/facade/simulate-capture.js +296 -55
- package/dist/facade/simulate-capture.js.map +1 -1
- package/dist/facade/subject-framing.d.ts +55 -0
- package/dist/facade/subject-framing.js +66 -0
- package/dist/facade/subject-framing.js.map +1 -0
- package/dist/gpu/chart-radiance-gpu.d.ts +8 -0
- package/dist/gpu/chart-radiance-gpu.js +20 -1
- package/dist/gpu/chart-radiance-gpu.js.map +1 -1
- package/dist/index.d.ts +5 -3
- package/dist/index.js +5 -3
- package/dist/index.js.map +1 -1
- package/docs/API_REFERENCE.md +48 -1
- package/docs/QUICK_START.md +264 -3
- package/docs/api/core-version.md +1 -1
- package/docs/api/equipment-generic-prime-lenses.md +85 -0
- package/docs/api/exports.json +167 -2
- package/docs/api/facade-chart-scenes.md +280 -4
- package/docs/api/facade-scene-radiance.md +42 -0
- package/docs/api/facade-simulate-capture.md +107 -2
- package/docs/api/facade-subject-framing.md +72 -0
- package/package.json +1 -1
|
@@ -2,6 +2,37 @@
|
|
|
2
2
|
|
|
3
3
|
The package and root API versions are recorded once in [Navigation](../API_REFERENCE.md) · [Developer guide](https://github.com/Photivra/photivra/blob/main/docs/DEVELOPERS.md). Generated signatures retain independent schema/model versions. Only the exports listed here are root-package contracts; module-local helpers are not supported deep imports.
|
|
4
4
|
|
|
5
|
+
## BarGroupsChartScene
|
|
6
|
+
|
|
7
|
+
2.3: groups of three dark bars on a light plate (the three-bar concept of the US Air Force 1951 target,
|
|
8
|
+
a US-government publication, in the engine's own arrangement): one group per frequency, vertical bars (horizontal resolution)
|
|
9
|
+
in the upper row and horizontal bars (vertical resolution) below, optionally labelled with engine-drawn
|
|
10
|
+
seven-segment numerals. Frequencies are line widths per picture height (LW/PH, as in ISO 12233), where
|
|
11
|
+
the picture height is the chart's height: one bar is PH/LW wide.
|
|
12
|
+
|
|
13
|
+
```ts
|
|
14
|
+
export interface BarGroupsChartScene {
|
|
15
|
+
preset: "bar-groups";
|
|
16
|
+
/** One group per entry, left to right: integers 1..100000. Default [100, 200, 400, 800]. 1..32 entries. */
|
|
17
|
+
lineWidthsPerPictureHeight?: readonly number[];
|
|
18
|
+
/** Draw each group's LW/PH value below it. Default true. */
|
|
19
|
+
numerals?: boolean;
|
|
20
|
+
darkReflectance?: number;
|
|
21
|
+
lightReflectance?: number;
|
|
22
|
+
}
|
|
23
|
+
```
|
|
24
|
+
|
|
25
|
+
## calculateBarGroupTargets
|
|
26
|
+
|
|
27
|
+
The bar groups of a `bar-groups` chart, or of every `bar-groups` element of a composite, in the chart's
|
|
28
|
+
frame units (2.3). `aspect` is the chart's height / width, as for {@link resolveChartScene}.
|
|
29
|
+
|
|
30
|
+
```ts
|
|
31
|
+
export function calculateBarGroupTargets(input: { scene: ChartScene; aspect: number }): ChartBarGroupTarget[];
|
|
32
|
+
```
|
|
33
|
+
|
|
34
|
+
This call is synchronous; any supplied provider must follow its explicit synchronous contract.
|
|
35
|
+
|
|
5
36
|
## calculatePointGridCenters
|
|
6
37
|
|
|
7
38
|
Centres (frame units) of a point grid: one disk centred in each of columns × rows equal cells, row-major from the top-left.
|
|
@@ -12,6 +43,18 @@ export function calculatePointGridCenters(input: { columns: number; rows: number
|
|
|
12
43
|
|
|
13
44
|
This call is synchronous; any supplied provider must follow its explicit synchronous contract.
|
|
14
45
|
|
|
46
|
+
## calculateSlantedSquareEdges
|
|
47
|
+
|
|
48
|
+
Squares and edges of a `slanted-squares` chart, or of every `slanted-squares` element of a composite, in
|
|
49
|
+
the chart's frame units (2.3), for slanted-edge regions of interest (Burns, PICS 2000). Directions are unit
|
|
50
|
+
vectors along each edge (u right, v up).
|
|
51
|
+
|
|
52
|
+
```ts
|
|
53
|
+
export function calculateSlantedSquareEdges(input: { scene: ChartScene; aspect: number }): ChartSlantedSquare[];
|
|
54
|
+
```
|
|
55
|
+
|
|
56
|
+
This call is synchronous; any supplied provider must follow its explicit synchronous contract.
|
|
57
|
+
|
|
15
58
|
## calculateStepWedgeReflectances
|
|
16
59
|
|
|
17
60
|
Step reflectances of a step wedge. `equal-density` spaces optical density D = -log10(R) evenly, which
|
|
@@ -24,6 +67,14 @@ export function calculateStepWedgeReflectances(input: { steps: number; minimumRe
|
|
|
24
67
|
|
|
25
68
|
This call is synchronous; any supplied provider must follow its explicit synchronous contract.
|
|
26
69
|
|
|
70
|
+
## CHART_CONTINUOUS_LEVELS
|
|
71
|
+
|
|
72
|
+
Neutral levels that represent a continuous pattern (grey ramp; 2.3 sine star, zone plate and dead-leaves greys).
|
|
73
|
+
|
|
74
|
+
```ts
|
|
75
|
+
CHART_CONTINUOUS_LEVELS = 1024
|
|
76
|
+
```
|
|
77
|
+
|
|
27
78
|
## CHART_SCENE_DEFAULTS
|
|
28
79
|
|
|
29
80
|
Engine-chosen chart parameters, each reported when the caller omitted it.
|
|
@@ -37,7 +88,16 @@ CHART_SCENE_DEFAULTS = Object.freeze({
|
|
|
37
88
|
"grey-ramp": Object.freeze({ minimumReflectance: 0.03, maximumReflectance: 0.9 }),
|
|
38
89
|
checkerboard: Object.freeze({ squaresAcross: 8, darkReflectance: 0.05, lightReflectance: 0.8 }),
|
|
39
90
|
"point-grid": Object.freeze({ columns: 5, rows: 3, radius: 0.01, pointReflectance: 0.9, backgroundReflectance: 0.02 }),
|
|
40
|
-
patches: Object.freeze({ gapFraction: 0.1, backgroundReflectance: 0.18 })
|
|
91
|
+
patches: Object.freeze({ gapFraction: 0.1, backgroundReflectance: 0.18 }),
|
|
92
|
+
"dead-leaves": Object.freeze({ radiusMinimum: 0.01, radiusMaximum: 0.5, minimumReflectance: 0.2, maximumReflectance: 0.6, seed: 1 }),
|
|
93
|
+
"bar-groups": Object.freeze({ lineWidthsPerPictureHeight: Object.freeze([100, 200, 400, 800]), numerals: true, darkReflectance: 0.05, lightReflectance: 0.8 }),
|
|
94
|
+
"hyperbolic-wedge": Object.freeze({ orientation: "horizontal" as const, lineCount: 5, minimumLineWidthsPerPictureHeight: 100,
|
|
95
|
+
maximumLineWidthsPerPictureHeight: 1000, darkReflectance: 0.05, lightReflectance: 0.8 }),
|
|
96
|
+
"zone-plate": Object.freeze({ radiusFraction: 0.9, maximumCyclesPerPictureHeight: 200, darkReflectance: 0.1, lightReflectance: 0.7, backgroundReflectance: 0.18 }),
|
|
97
|
+
"slanted-squares": Object.freeze({ columns: 3, rows: 2, sizeFraction: 0.5, angleDegrees: 5, darkReflectance: 0.15, lightReflectance: 0.6 }),
|
|
98
|
+
"line-grid": Object.freeze({ spacing: 1 / 3, lineWidth: 0.01, lineReflectance: 0.42, backgroundReflectance: 0.6 }),
|
|
99
|
+
fiducial: Object.freeze({ radiusFraction: 0.8, ringFraction: 0.18, inverted: false, darkReflectance: 0.05, lightReflectance: 0.8, backgroundReflectance: 0.18 }),
|
|
100
|
+
composite: Object.freeze({ background: Object.freeze({ preset: "uniform" as const, reflectance: 0.18 }) })
|
|
41
101
|
})
|
|
42
102
|
```
|
|
43
103
|
|
|
@@ -47,7 +107,8 @@ The exact contract is declared below; use the domain guide for assumptions and s
|
|
|
47
107
|
|
|
48
108
|
```ts
|
|
49
109
|
CHART_SCENE_PRESETS: readonly ChartScenePresetId[] = Object.freeze(["uniform", "slanted-edge", "siemens-star",
|
|
50
|
-
"step-wedge", "grey-ramp", "checkerboard", "point-grid", "patches"
|
|
110
|
+
"step-wedge", "grey-ramp", "checkerboard", "point-grid", "patches", "dead-leaves", "bar-groups", "hyperbolic-wedge", "zone-plate",
|
|
111
|
+
"slanted-squares", "line-grid", "fiducial", "composite"] as const)
|
|
51
112
|
```
|
|
52
113
|
|
|
53
114
|
## CHART_SPECTRAL_RANGE_NANOMETERS
|
|
@@ -58,6 +119,43 @@ Wavelength range every chart spectrum must cover (the facade's sensor quadrature
|
|
|
58
119
|
CHART_SPECTRAL_RANGE_NANOMETERS = Object.freeze({ minimum: 380, maximum: 780 })
|
|
59
120
|
```
|
|
60
121
|
|
|
122
|
+
## ChartBarGroupTarget
|
|
123
|
+
|
|
124
|
+
One bar group of a `bar-groups` chart or composite element, in the chart's frame units.
|
|
125
|
+
|
|
126
|
+
```ts
|
|
127
|
+
export interface ChartBarGroupTarget {
|
|
128
|
+
/** Composite element index, or null for a plain `bar-groups` chart. */
|
|
129
|
+
elementIndex: number | null;
|
|
130
|
+
lineWidthsPerPictureHeight: number;
|
|
131
|
+
/** Line pairs (cycles) per picture height: LW/PH ÷ 2. */
|
|
132
|
+
cyclesPerPictureHeight: number;
|
|
133
|
+
/** Width of one bar, frame units. */
|
|
134
|
+
lineWidth: number;
|
|
135
|
+
/** The three vertical bars (horizontal resolution) and the three horizontal bars (vertical resolution). */
|
|
136
|
+
verticalBars: ChartRectangle;
|
|
137
|
+
horizontalBars: ChartRectangle;
|
|
138
|
+
}
|
|
139
|
+
```
|
|
140
|
+
|
|
141
|
+
## ChartElementScene
|
|
142
|
+
|
|
143
|
+
Any chart preset except `composite`: a composite's background or element.
|
|
144
|
+
|
|
145
|
+
```ts
|
|
146
|
+
export type ChartElementScene = UniformChartScene | SlantedEdgeChartScene | SiemensStarChartScene | StepWedgeChartScene | GreyRampChartScene |
|
|
147
|
+
CheckerboardChartScene | PointGridChartScene | PatchChartScene | DeadLeavesChartScene | BarGroupsChartScene | HyperbolicWedgeChartScene |
|
|
148
|
+
ZonePlateChartScene | SlantedSquaresChartScene | LineGridChartScene | FiducialChartScene;
|
|
149
|
+
```
|
|
150
|
+
|
|
151
|
+
## ChartRectangle
|
|
152
|
+
|
|
153
|
+
An axis-aligned rectangle in chart frame units: u0 ≤ u ≤ u1, v0 ≤ v ≤ v1.
|
|
154
|
+
|
|
155
|
+
```ts
|
|
156
|
+
export interface ChartRectangle { u0: number; v0: number; u1: number; v1: number }
|
|
157
|
+
```
|
|
158
|
+
|
|
61
159
|
## ChartReflectance
|
|
62
160
|
|
|
63
161
|
A neutral (spectrally flat) reflectance in [0, 1], or a caller reflectance spectrum (values in [0, 1]).
|
|
@@ -71,8 +169,7 @@ export type ChartReflectance = number | ColorimetricSpectrum;
|
|
|
71
169
|
The exact contract is declared below; use the domain guide for assumptions and staged integration.
|
|
72
170
|
|
|
73
171
|
```ts
|
|
74
|
-
export type ChartScene =
|
|
75
|
-
GreyRampChartScene | CheckerboardChartScene | PointGridChartScene | PatchChartScene;
|
|
172
|
+
export type ChartScene = ChartElementScene | CompositeChartScene;
|
|
76
173
|
```
|
|
77
174
|
|
|
78
175
|
## ChartScenePresetId
|
|
@@ -83,6 +180,25 @@ The exact contract is declared below; use the domain guide for assumptions and s
|
|
|
83
180
|
export type ChartScenePresetId = ChartScene["preset"];
|
|
84
181
|
```
|
|
85
182
|
|
|
183
|
+
## ChartSlantedSquare
|
|
184
|
+
|
|
185
|
+
One square of a `slanted-squares` chart and its four edges, in the chart's frame units.
|
|
186
|
+
|
|
187
|
+
```ts
|
|
188
|
+
export interface ChartSlantedSquare {
|
|
189
|
+
elementIndex: number | null;
|
|
190
|
+
center: { u: number; v: number };
|
|
191
|
+
/** Side length, frame units. */
|
|
192
|
+
side: number;
|
|
193
|
+
/** Clockwise rotation, degrees. */
|
|
194
|
+
angleDegrees: number;
|
|
195
|
+
darkReflectance: number;
|
|
196
|
+
lightReflectance: number;
|
|
197
|
+
/** `left`/`right` edges are near-vertical (horizontal MTF), `top`/`bottom` near-horizontal (vertical MTF). */
|
|
198
|
+
edges: { side: "left" | "right" | "top" | "bottom"; midpoint: { u: number; v: number }; direction: { u: number; v: number }; length: number }[];
|
|
199
|
+
}
|
|
200
|
+
```
|
|
201
|
+
|
|
86
202
|
## CheckerboardChartScene
|
|
87
203
|
|
|
88
204
|
The exact contract is declared below; use the domain guide for assumptions and staged integration.
|
|
@@ -97,6 +213,82 @@ export interface CheckerboardChartScene {
|
|
|
97
213
|
}
|
|
98
214
|
```
|
|
99
215
|
|
|
216
|
+
## CompositeChartElement
|
|
217
|
+
|
|
218
|
+
One element of a composite chart: a preset drawn inside its placement rectangle (frame units of the
|
|
219
|
+
composite). The element sees its own frame: u = ±1 at the rectangle's left and right edges, aspect =
|
|
220
|
+
height / width, and LW/PH frequencies still refer to the composite's picture height.
|
|
221
|
+
|
|
222
|
+
```ts
|
|
223
|
+
export interface CompositeChartElement {
|
|
224
|
+
scene: ChartElementScene;
|
|
225
|
+
centerU: number;
|
|
226
|
+
centerV: number;
|
|
227
|
+
width: number;
|
|
228
|
+
height: number;
|
|
229
|
+
/** `rectangle` (default) or `ellipse` inscribed in the rectangle; outside it, earlier elements or the background show. */
|
|
230
|
+
mask?: "rectangle" | "ellipse";
|
|
231
|
+
}
|
|
232
|
+
```
|
|
233
|
+
|
|
234
|
+
## CompositeChartScene
|
|
235
|
+
|
|
236
|
+
2.3: an ordered list of elements over a background. Later elements cover earlier ones. The engine
|
|
237
|
+
provides only the generic parts; a branded or product-specific layout stays in the application.
|
|
238
|
+
|
|
239
|
+
```ts
|
|
240
|
+
export interface CompositeChartScene {
|
|
241
|
+
preset: "composite";
|
|
242
|
+
/** Fills the whole composite frame. Default `{ preset: "uniform", reflectance: 0.18 }`. */
|
|
243
|
+
background?: ChartElementScene;
|
|
244
|
+
/** 1..256 elements, drawn in order. */
|
|
245
|
+
elements: readonly CompositeChartElement[];
|
|
246
|
+
}
|
|
247
|
+
```
|
|
248
|
+
|
|
249
|
+
## DeadLeavesChartScene
|
|
250
|
+
|
|
251
|
+
2.3: seeded dead-leaves texture (Matheron's random closed set model, in the scale-invariant form used for
|
|
252
|
+
camera texture measurement by Cao, Guichard and Hornung): opaque disks with Poisson-distributed centres,
|
|
253
|
+
radius density ∝ r⁻³ on [radiusMinimum, radiusMaximum] and a grey drawn uniformly in [minimum, maximum]
|
|
254
|
+
reflectance. Disks are drawn in order with earlier disks on top until every point of the chart (plus 0.1
|
|
255
|
+
frame units around it) is covered, which samples the stationary dead-leaves image exactly (Kendall and
|
|
256
|
+
Thönnes' backward "perfect simulation"). Radii are in frame units (fraction of the frame half-width).
|
|
257
|
+
|
|
258
|
+
```ts
|
|
259
|
+
export interface DeadLeavesChartScene {
|
|
260
|
+
preset: "dead-leaves";
|
|
261
|
+
/** Smallest disk radius, frame units, [0.002, radiusMaximum). Default 0.01. */
|
|
262
|
+
radiusMinimum?: number;
|
|
263
|
+
/** Largest disk radius, frame units, (radiusMinimum, 2]. Default 0.5. */
|
|
264
|
+
radiusMaximum?: number;
|
|
265
|
+
/** Grey range (neutral reflectances). Defaults 0.2 and 0.6. */
|
|
266
|
+
minimumReflectance?: number;
|
|
267
|
+
maximumReflectance?: number;
|
|
268
|
+
/** Random seed (uint32); the same seed gives the same disks on every platform. Default 1. */
|
|
269
|
+
seed?: number;
|
|
270
|
+
}
|
|
271
|
+
```
|
|
272
|
+
|
|
273
|
+
## FiducialChartScene
|
|
274
|
+
|
|
275
|
+
2.3: registration fiducial: a 2 × 2 checker disk inside a dark ring; `inverted` swaps the checker phase (an orientation cue).
|
|
276
|
+
|
|
277
|
+
```ts
|
|
278
|
+
export interface FiducialChartScene {
|
|
279
|
+
preset: "fiducial";
|
|
280
|
+
/** Disk radius as a fraction of the frame half-height, (0, 1]. Default 0.8. */
|
|
281
|
+
radiusFraction?: number;
|
|
282
|
+
/** Ring width as a fraction of the radius, (0, 1). Default 0.18. */
|
|
283
|
+
ringFraction?: number;
|
|
284
|
+
/** Default false: the upper-right and lower-left quadrants are dark. */
|
|
285
|
+
inverted?: boolean;
|
|
286
|
+
darkReflectance?: number;
|
|
287
|
+
lightReflectance?: number;
|
|
288
|
+
backgroundReflectance?: number;
|
|
289
|
+
}
|
|
290
|
+
```
|
|
291
|
+
|
|
100
292
|
## GreyRampChartScene
|
|
101
293
|
|
|
102
294
|
The exact contract is declared below; use the domain guide for assumptions and staged integration.
|
|
@@ -110,6 +302,43 @@ export interface GreyRampChartScene {
|
|
|
110
302
|
}
|
|
111
303
|
```
|
|
112
304
|
|
|
305
|
+
## HyperbolicWedgeChartScene
|
|
306
|
+
|
|
307
|
+
2.3: hyperbolic wedge: `lineCount` dark lines separated by light gaps of the same width, whose width
|
|
308
|
+
shrinks along the wedge axis so that the frequency rises linearly from the minimum to the maximum LW/PH.
|
|
309
|
+
The line edges are hyperbolas. `horizontal`: the axis runs left to right and the lines are nearly
|
|
310
|
+
horizontal (vertical resolution); `vertical`: the axis runs bottom to top (horizontal resolution).
|
|
311
|
+
|
|
312
|
+
```ts
|
|
313
|
+
export interface HyperbolicWedgeChartScene {
|
|
314
|
+
preset: "hyperbolic-wedge";
|
|
315
|
+
orientation?: "horizontal" | "vertical";
|
|
316
|
+
/** Dark lines, 1..50. Default 5. */
|
|
317
|
+
lineCount?: number;
|
|
318
|
+
/** LW/PH at the start and end of the axis. Defaults 100 and 1000. */
|
|
319
|
+
minimumLineWidthsPerPictureHeight?: number;
|
|
320
|
+
maximumLineWidthsPerPictureHeight?: number;
|
|
321
|
+
darkReflectance?: number;
|
|
322
|
+
lightReflectance?: number;
|
|
323
|
+
}
|
|
324
|
+
```
|
|
325
|
+
|
|
326
|
+
## LineGridChartScene
|
|
327
|
+
|
|
328
|
+
2.3: straight lines at every multiple of `spacing` from the centre in u and v (a distortion and registration grid).
|
|
329
|
+
|
|
330
|
+
```ts
|
|
331
|
+
export interface LineGridChartScene {
|
|
332
|
+
preset: "line-grid";
|
|
333
|
+
/** Distance between lines, frame units, (0, 2]. Default 1/3 (six cells across). */
|
|
334
|
+
spacing?: number;
|
|
335
|
+
/** Line width, frame units, (0, spacing). Default 0.01. */
|
|
336
|
+
lineWidth?: number;
|
|
337
|
+
lineReflectance?: number;
|
|
338
|
+
backgroundReflectance?: number;
|
|
339
|
+
}
|
|
340
|
+
```
|
|
341
|
+
|
|
113
342
|
## PatchChartScene
|
|
114
343
|
|
|
115
344
|
The exact contract is declared below; use the domain guide for assumptions and staged integration.
|
|
@@ -196,6 +425,13 @@ export interface SiemensStarChartScene {
|
|
|
196
425
|
lightReflectance?: number;
|
|
197
426
|
/** Reflectance outside the star. Default 0.18. */
|
|
198
427
|
backgroundReflectance?: number;
|
|
428
|
+
/**
|
|
429
|
+
* 2.3: angular reflectance profile. `bar` (default): square-wave sectors. `sine`: a sinusoidal star,
|
|
430
|
+
* R(θ) = mid + amp·sin(2π·cycles·(θ/2π + ½)) between the dark and light reflectances, zero crossings at
|
|
431
|
+
* the bar star's sector edges, quantized to {@link CHART_CONTINUOUS_LEVELS} levels. Reported in the
|
|
432
|
+
* parameters only when given, so 2.2 scene digests are unchanged.
|
|
433
|
+
*/
|
|
434
|
+
profile?: "bar" | "sine";
|
|
199
435
|
}
|
|
200
436
|
```
|
|
201
437
|
|
|
@@ -215,6 +451,27 @@ export interface SlantedEdgeChartScene {
|
|
|
215
451
|
}
|
|
216
452
|
```
|
|
217
453
|
|
|
454
|
+
## SlantedSquaresChartScene
|
|
455
|
+
|
|
456
|
+
2.3: a field of dark squares rotated clockwise by `angleDegrees` on a light background, one centred in
|
|
457
|
+
each of columns × rows equal cells: every square gives two near-vertical and two near-horizontal slanted
|
|
458
|
+
edges (Burns, PICS 2000). See {@link calculateSlantedSquareEdges}.
|
|
459
|
+
|
|
460
|
+
```ts
|
|
461
|
+
export interface SlantedSquaresChartScene {
|
|
462
|
+
preset: "slanted-squares";
|
|
463
|
+
columns?: number;
|
|
464
|
+
rows?: number;
|
|
465
|
+
/** Square side as a fraction of the smaller cell side, (0, 1); the rotated square must stay in its cell. Default 0.5. */
|
|
466
|
+
sizeFraction?: number;
|
|
467
|
+
/** Clockwise rotation, degrees, in (-45, 45). Default 5. */
|
|
468
|
+
angleDegrees?: number;
|
|
469
|
+
/** Square (dark) and background (light) reflectances. Defaults 0.15 and 0.6 (4:1). */
|
|
470
|
+
darkReflectance?: number;
|
|
471
|
+
lightReflectance?: number;
|
|
472
|
+
}
|
|
473
|
+
```
|
|
474
|
+
|
|
218
475
|
## StepWedgeChartScene
|
|
219
476
|
|
|
220
477
|
The exact contract is declared below; use the domain guide for assumptions and staged integration.
|
|
@@ -238,3 +495,22 @@ The exact contract is declared below; use the domain guide for assumptions and s
|
|
|
238
495
|
```ts
|
|
239
496
|
export interface UniformChartScene { preset: "uniform"; reflectance?: ChartReflectance }
|
|
240
497
|
```
|
|
498
|
+
|
|
499
|
+
## ZonePlateChartScene
|
|
500
|
+
|
|
501
|
+
2.3: circular zone plate R(r) = mid + amp·cos(π·k·r²): the local frequency k·r rises linearly from 0 at
|
|
502
|
+
the centre to `maximumCyclesPerPictureHeight` at the rim (the quadratic-phase chirp of a Fresnel zone
|
|
503
|
+
plate). Quantized to {@link CHART_CONTINUOUS_LEVELS} levels.
|
|
504
|
+
|
|
505
|
+
```ts
|
|
506
|
+
export interface ZonePlateChartScene {
|
|
507
|
+
preset: "zone-plate";
|
|
508
|
+
/** Plate radius as a fraction of the frame half-height, (0, 1]. Default 0.9. */
|
|
509
|
+
radiusFraction?: number;
|
|
510
|
+
/** Frequency at the rim, cycles per picture height. Default 200. */
|
|
511
|
+
maximumCyclesPerPictureHeight?: number;
|
|
512
|
+
darkReflectance?: number;
|
|
513
|
+
lightReflectance?: number;
|
|
514
|
+
backgroundReflectance?: number;
|
|
515
|
+
}
|
|
516
|
+
```
|
|
@@ -32,6 +32,29 @@ export type CaptureIlluminant =
|
|
|
32
32
|
| { kind: "spectrum"; spectrum: ColorimetricSpectrum; label?: string };
|
|
33
33
|
```
|
|
34
34
|
|
|
35
|
+
## CHART_SIZE_DEFAULT_SURROUND_REFLECTANCE
|
|
36
|
+
|
|
37
|
+
Default surround of a fixed-size chart: an 18 % grey plane.
|
|
38
|
+
|
|
39
|
+
```ts
|
|
40
|
+
CHART_SIZE_DEFAULT_SURROUND_REFLECTANCE = 0.18
|
|
41
|
+
```
|
|
42
|
+
|
|
43
|
+
## ChartSizeOption
|
|
44
|
+
|
|
45
|
+
2.3: a chart's physical size on the scene plane (`simulateCapture` `chartSize`, `createPlanarSceneRadianceProvider` `chartSize`).
|
|
46
|
+
|
|
47
|
+
```ts
|
|
48
|
+
export interface ChartSizeOption {
|
|
49
|
+
/** Chart width in metres, (0, 10 000]. */
|
|
50
|
+
widthM: number;
|
|
51
|
+
/** Chart height in metres. Default: widthM × the frame aspect (height / width), so the chart has the frame's shape. */
|
|
52
|
+
heightM?: number;
|
|
53
|
+
/** Neutral reflectance of the plane around the chart, lit by the same illuminant. Default 0.18. */
|
|
54
|
+
surroundReflectance?: number;
|
|
55
|
+
}
|
|
56
|
+
```
|
|
57
|
+
|
|
35
58
|
## createPlanarSceneRadianceProvider
|
|
36
59
|
|
|
37
60
|
Public scene-preset provider. Places an engine chart (or a caller reflectance or radiance function) on
|
|
@@ -51,6 +74,11 @@ export function createPlanarSceneRadianceProvider(input: {
|
|
|
51
74
|
aspect: number;
|
|
52
75
|
sceneId: string;
|
|
53
76
|
providerProfileId: string;
|
|
77
|
+
/**
|
|
78
|
+
* 2.3, opt-in: place the chart at this physical size, centred, instead of filling the frame; the chart preset
|
|
79
|
+
* is resolved with aspect heightM / widthM and the rest of the plane is the surround.
|
|
80
|
+
*/
|
|
81
|
+
chartSize?: ChartSizeOption;
|
|
54
82
|
}): PlanarSceneRadianceProvider & { chart: ResolvedChartScene | null };
|
|
55
83
|
```
|
|
56
84
|
|
|
@@ -76,6 +104,13 @@ export interface PlanarSceneRadianceProvider {
|
|
|
76
104
|
evaluateApertureRadiance(request: Readonly<SceneRadianceEvaluationRequest>, ray: Readonly<SensorApertureRay>): SceneRadianceEvaluationResult;
|
|
77
105
|
/** Spectral radiance at a plane point (frame units), the same value the callbacks return. */
|
|
78
106
|
radianceAt(u: number, v: number, wavelengthNanometers: number): number;
|
|
107
|
+
/**
|
|
108
|
+
* 2.3, chart scenes only: the chart material at a plane point (frame units), or `materials.length` for the
|
|
109
|
+
* surround of a fixed-size chart; `materialRadiance` gives that material's spectral radiance, the same value
|
|
110
|
+
* `radianceAt` returns at its points.
|
|
111
|
+
*/
|
|
112
|
+
chartMaterialAt?(u: number, v: number): number;
|
|
113
|
+
materialRadiance?(material: number, wavelengthNanometers: number): number;
|
|
79
114
|
}
|
|
80
115
|
```
|
|
81
116
|
|
|
@@ -118,5 +153,12 @@ export interface ScenePlanePoint {
|
|
|
118
153
|
u: number;
|
|
119
154
|
v: number;
|
|
120
155
|
wavelengthNanometers: number;
|
|
156
|
+
/**
|
|
157
|
+
* 2.3, only with a fixed-size chart (`chartSize`): the point in chart-local frame units (±1 at the chart's
|
|
158
|
+
* left/right edges, v up on the same scale, ±chart height/width at its top/bottom). The function is then
|
|
159
|
+
* called only for points on the chart; the surround is the placement's surround reflectance.
|
|
160
|
+
*/
|
|
161
|
+
chartU?: number;
|
|
162
|
+
chartV?: number;
|
|
121
163
|
}
|
|
122
164
|
```
|
|
@@ -2,6 +2,38 @@
|
|
|
2
2
|
|
|
3
3
|
The package and root API versions are recorded once in [Navigation](../API_REFERENCE.md) · [Developer guide](https://github.com/Photivra/photivra/blob/main/docs/DEVELOPERS.md). Generated signatures retain independent schema/model versions. Only the exports listed here are root-package contracts; module-local helpers are not supported deep imports.
|
|
4
4
|
|
|
5
|
+
## IdealReferenceResult
|
|
6
|
+
|
|
7
|
+
Result of {@link simulateIdealReference}: an ideal reference image, not a capture (no RAW, plan or request).
|
|
8
|
+
|
|
9
|
+
```ts
|
|
10
|
+
export interface IdealReferenceResult {
|
|
11
|
+
kind: "ideal-reference";
|
|
12
|
+
/** Human-readable label for a user interface. */
|
|
13
|
+
label: string;
|
|
14
|
+
facadeVersion: typeof SIMULATE_CAPTURE_FACADE_VERSION;
|
|
15
|
+
engineApiVersion: string;
|
|
16
|
+
image: { width: number; height: number; format: SimulateCaptureOutputFormat; samples: Uint8Array | Uint16Array; png?: Uint8Array; colorEncoding?: SimulateCaptureColorEncoding };
|
|
17
|
+
/** The resolved exposure of the capture this reference matches. */
|
|
18
|
+
exposure: { mode: SimulateCaptureExposureMode; settings: { fNumber: number; shutterSeconds: number; iso: number }; ev100: number };
|
|
19
|
+
scene: SimulateCaptureResult["scene"];
|
|
20
|
+
region?: { x: number; y: number; width: number; height: number; frameWidth: number; frameHeight: number };
|
|
21
|
+
diagnostics: { sampleCount: number; timingsMs: { reference: number; total: number } };
|
|
22
|
+
provenance: { scientificStatus: "approximation"; cameraPresetId: string; cameraPresetVersion: string; evidence: readonly EvidenceProvenance[];
|
|
23
|
+
composedContracts: readonly string[]; limitations: readonly string[] };
|
|
24
|
+
/** The capture request's assumptions, then `reference.kind`, `reference.excludes`, `reference.exposure` and `reference.sampling`. */
|
|
25
|
+
assumptions: readonly SimulateCaptureAssumption[];
|
|
26
|
+
}
|
|
27
|
+
```
|
|
28
|
+
|
|
29
|
+
## SIMULATE_CAPTURE_BOX_APERTURE_DEFAULT_SAMPLES
|
|
30
|
+
|
|
31
|
+
Default midpoint samples per axis of `sensor.pixelAperture: "box"`.
|
|
32
|
+
|
|
33
|
+
```ts
|
|
34
|
+
SIMULATE_CAPTURE_BOX_APERTURE_DEFAULT_SAMPLES = 4
|
|
35
|
+
```
|
|
36
|
+
|
|
5
37
|
## SIMULATE_CAPTURE_COST_OPTIONS
|
|
6
38
|
|
|
7
39
|
Options reported in `diagnostics.options` (2.1), in this order, when they ran: the ones that change how much work
|
|
@@ -9,7 +41,7 @@ a capture does. `motion.rotation` is a non-zero angular velocity; `sensor.tempor
|
|
|
9
41
|
|
|
10
42
|
```ts
|
|
11
43
|
SIMULATE_CAPTURE_COST_OPTIONS = Object.freeze(["lens.pupilSampling", "lens.projection", "lens.distortion", "lens.vignetting", "lens.psf",
|
|
12
|
-
"lens.diffraction", "sensor.antiAliasing", "sensor.temporalSampleCount", "motion.rotation", "motion.shutter.rolling", "output.borderHandling.mirror",
|
|
44
|
+
"lens.diffraction", "sensor.antiAliasing", "sensor.pixelAperture.box", "sensor.temporalSampleCount", "motion.rotation", "motion.shutter.rolling", "output.borderHandling.mirror", "output.region",
|
|
13
45
|
"output.whiteBalance.auto", "output.demosaic.ahd", "output.highlightMode.reconstruct", "output.colorEncoding.wide-gamut", "output.gamutMapping.perceptual",
|
|
14
46
|
"output.format.jpeg", "output.format.png", "output.format.dng"] as const)
|
|
15
47
|
```
|
|
@@ -144,6 +176,14 @@ export interface SimulateCaptureOptions {
|
|
|
144
176
|
lens?: {
|
|
145
177
|
/** Must lie in the lens capability (the generic primes are 50 mm). Default: the lens's shortest focal length. */
|
|
146
178
|
focalLengthMm?: number;
|
|
179
|
+
/**
|
|
180
|
+
* Opt-in (2.3): a lens of the generic prime family by its full-frame-equivalent focal length
|
|
181
|
+
* (`GENERIC_PRIME_EQUIVALENT_FOCAL_LENGTHS_MM`). Its physical focal length is the equivalent ÷ the diagonal crop
|
|
182
|
+
* factor of the simulated frame (output width × height × pixel pitch); it replaces the tier lens's focal length and
|
|
183
|
+
* f-number range (the tier lens's transmission is kept). An f-number outside the prime's range, or a subject or
|
|
184
|
+
* focus distance below its minimum focus distance, is rejected. Not combinable with `focalLengthMm`.
|
|
185
|
+
*/
|
|
186
|
+
prime?: number;
|
|
147
187
|
/** Aperture for manual and aperture-priority modes. Default 8. */
|
|
148
188
|
fNumber?: number;
|
|
149
189
|
/** Focus distance in metres. Default: the subject distance. */
|
|
@@ -183,6 +223,14 @@ export interface SimulateCaptureOptions {
|
|
|
183
223
|
scene: ChartScene | CallerReflectanceScene | CallerRadianceScene;
|
|
184
224
|
/** Distance from the camera to the scene plane in metres. Default 5. */
|
|
185
225
|
subjectDistanceM?: number;
|
|
226
|
+
/**
|
|
227
|
+
* Opt-in (2.3) fixed-size chart: place the scene at this physical size on the plane at the subject distance,
|
|
228
|
+
* centred on the optical axis, instead of sizing it to fill the frame. Outside it the plane is a neutral surround
|
|
229
|
+
* (default 18 %). Chart presets are resolved in the chart's own frame (aspect heightM / widthM); caller functions
|
|
230
|
+
* are called only on the chart and receive chart-local `chartU`, `chartV`. `result.scene.chart` reports the
|
|
231
|
+
* framed width, the fraction of the frame the chart covers and the thin-lens magnification.
|
|
232
|
+
*/
|
|
233
|
+
chartSize?: ChartSizeOption;
|
|
186
234
|
/** Default: Planckian 6500 K (a blackbody stand-in for daylight; CIE D65 is not bundled). */
|
|
187
235
|
illuminant?: CaptureIlluminant;
|
|
188
236
|
/** Illuminance on the scene plane, lux. Default about 21 481 lux (see `SIMULATE_CAPTURE_DEFAULT_ILLUMINANCE_LUX` and the assumptions). */
|
|
@@ -225,6 +273,15 @@ export interface SimulateCaptureOptions {
|
|
|
225
273
|
* memory grow with the pixel count (see "Large images" in the quick start); browsers may fail at large sizes.
|
|
226
274
|
*/
|
|
227
275
|
maximumPixels?: number;
|
|
276
|
+
/**
|
|
277
|
+
* Opt-in (2.3) region rendering: render only this rectangle, in output-pixel coordinates of the whole frame
|
|
278
|
+
* `width` × `height` (x right, y down from its top-left). The pixels are byte-identical to the same pixels of
|
|
279
|
+
* the whole render: framing, metering, exposure, noise seeds (absolute native site indices), rolling-shutter row
|
|
280
|
+
* timing, diffraction and demosaic all use the whole frame. Use it to tile a large frame across workers or to
|
|
281
|
+
* render a 100 % crop. `result.image` is the region; `result.region` reports it. Not combinable with
|
|
282
|
+
* `whiteBalance: "auto"`, whose statistics would come from the region only.
|
|
283
|
+
*/
|
|
284
|
+
region?: { x: number; y: number; width: number; height: number };
|
|
228
285
|
};
|
|
229
286
|
/** Camera motion and shutter type. Default: still camera, global electronic shutter. */
|
|
230
287
|
motion?: SimulateCaptureMotion;
|
|
@@ -242,6 +299,13 @@ export interface SimulateCaptureOptions {
|
|
|
242
299
|
* Multiplies the scene queries by the number of split points. Default off (the tiers declare no filter).
|
|
243
300
|
*/
|
|
244
301
|
antiAliasing?: SimulateCaptureSensorAntiAliasing;
|
|
302
|
+
/**
|
|
303
|
+
* Opt-in (2.3) pixel aperture. `"point"` (default): each site samples the irradiance at its centre.
|
|
304
|
+
* `"box"`: each site integrates the irradiance over its whole square photosite (fill factor 1) with an
|
|
305
|
+
* N × N midpoint rule, N = `samplesPerAxis` (1–16, default 4), so detail finer than a pixel averages out as
|
|
306
|
+
* on a real sensor (pixel MTF |sinc(f·p)|) instead of aliasing. Multiplies the scene queries by N².
|
|
307
|
+
*/
|
|
308
|
+
pixelAperture?: SimulateCapturePixelAperture;
|
|
245
309
|
};
|
|
246
310
|
/** Aborting cancels the running task; the promise rejects with a domain error and returns no partial image. */
|
|
247
311
|
signal?: AbortSignal;
|
|
@@ -258,6 +322,14 @@ The exact contract is declared below; use the domain guide for assumptions and s
|
|
|
258
322
|
export type SimulateCaptureOutputFormat = "srgb-8" | "srgb-16" | "jpeg" | "png" | "dng";
|
|
259
323
|
```
|
|
260
324
|
|
|
325
|
+
## SimulateCapturePixelAperture
|
|
326
|
+
|
|
327
|
+
Pixel aperture (2.3): centre sampling, or the square photosite integrated with an N × N midpoint rule.
|
|
328
|
+
|
|
329
|
+
```ts
|
|
330
|
+
export type SimulateCapturePixelAperture = "point" | "box" | { kind: "box"; samplesPerAxis?: number };
|
|
331
|
+
```
|
|
332
|
+
|
|
261
333
|
## SimulateCaptureProgress
|
|
262
334
|
|
|
263
335
|
The exact contract is declared below; use the domain guide for assumptions and staged integration.
|
|
@@ -293,9 +365,19 @@ export interface SimulateCaptureResult {
|
|
|
293
365
|
/** Lossless uncompressed CFA DNG of the packed RAW when format is "dng" (`serializeNativeRawDng`); `samples` are then sRGB 8-bit. */
|
|
294
366
|
dng?: Uint8Array;
|
|
295
367
|
};
|
|
296
|
-
/**
|
|
368
|
+
/**
|
|
369
|
+
* Packed native RAW (codes, black levels, saturation flags) as produced by the native environment RAW task. With
|
|
370
|
+
* `output.region` (2.3): the region's native sites only, with `plan` describing that raster (its active area is the
|
|
371
|
+
* region); `request.environmentRaw` and `request.siteInput` stay those of the whole frame.
|
|
372
|
+
*/
|
|
297
373
|
raw: NativeRawOutput;
|
|
298
374
|
plan: NativeRawPlan;
|
|
375
|
+
/**
|
|
376
|
+
* 2.3, present with `output.region`: the rendered rectangle in output pixels of the whole `frameWidth` × `frameHeight`
|
|
377
|
+
* frame, and the native sites rendered for it (`nativeRect`, in the whole frame's native raster: the region, the
|
|
378
|
+
* demosaic reach on each side clipped to the raster, and its origin rounded down to the 2 × 2 CFA repeat).
|
|
379
|
+
*/
|
|
380
|
+
region?: { x: number; y: number; width: number; height: number; frameWidth: number; frameHeight: number; nativeRect: { x: number; y: number; width: number; height: number } };
|
|
299
381
|
/** The complete underlying request. */
|
|
300
382
|
request: {
|
|
301
383
|
environmentRaw: NativeEnvironmentRawInput;
|
|
@@ -330,6 +412,14 @@ export interface SimulateCaptureResult {
|
|
|
330
412
|
/** Physical size of the framed scene plane, metres. */
|
|
331
413
|
framedWidthM: number;
|
|
332
414
|
framedHeightM: number;
|
|
415
|
+
/**
|
|
416
|
+
* 2.3, present with `chartSize`: the chart's physical size and surround, the fraction of the frame width and
|
|
417
|
+
* height it covers (above 1 when it is larger than the frame and cropped), the thin-lens magnification
|
|
418
|
+
* v/d (image distance over subject distance, the scale the facade's framing uses) and the chart's size on the
|
|
419
|
+
* sensor in millimetres and output pixels.
|
|
420
|
+
*/
|
|
421
|
+
chart?: { widthM: number; heightM: number; surroundReflectance: number; frameWidthFraction: number; frameHeightFraction: number;
|
|
422
|
+
magnification: number; imageWidthMm: number; imageHeightMm: number; imageWidthPixels: number; imageHeightPixels: number };
|
|
333
423
|
/**
|
|
334
424
|
* SHA-256 of the canonical scene description, recorded as the capture source digest. Caller spectra (a
|
|
335
425
|
* `spectrum` or `daylight` illuminant, chart reflectance spectra) are part of the description: tabulated
|
|
@@ -402,3 +492,18 @@ export type SimulateCaptureWhiteBalance =
|
|
|
402
492
|
| { kelvin: number; tint?: number }
|
|
403
493
|
| { channelGains: { red: number; green: number; blue: number } };
|
|
404
494
|
```
|
|
495
|
+
|
|
496
|
+
## simulateIdealReference
|
|
497
|
+
|
|
498
|
+
The ideal reference of a capture request (2.3): the same scene, framing, chart size, output size, region and pixel
|
|
499
|
+
grid as `simulateCapture(options)` would use, rendered with no camera effects (no lens blur, diffraction, defocus,
|
|
500
|
+
distortion, vignetting, anti-aliasing filter, mosaic or demosaic, noise, dark signal or motion), at the capture's
|
|
501
|
+
own exposure and developed with its white balance, colour matrices, tone curve and encoding (the
|
|
502
|
+
`reference.exposure` assumption). Deterministic and cheap: no RAW is simulated. Formats srgb-8, srgb-16 and png.
|
|
503
|
+
The result is labelled `kind: "ideal-reference"`; it is not a capture.
|
|
504
|
+
|
|
505
|
+
```ts
|
|
506
|
+
export async function simulateIdealReference(options: SimulateCaptureOptions): Promise<IdealReferenceResult>;
|
|
507
|
+
```
|
|
508
|
+
|
|
509
|
+
This call is asynchronous; byte hashing uses the caller runtime's Web Crypto.
|
|
@@ -0,0 +1,72 @@
|
|
|
1
|
+
# facade/subject-framing.ts public contracts
|
|
2
|
+
|
|
3
|
+
The package and root API versions are recorded once in [Navigation](../API_REFERENCE.md) · [Developer guide](https://github.com/Photivra/photivra/blob/main/docs/DEVELOPERS.md). Generated signatures retain independent schema/model versions. Only the exports listed here are root-package contracts; module-local helpers are not supported deep imports.
|
|
4
|
+
|
|
5
|
+
## calculateSubjectDistanceForFraming
|
|
6
|
+
|
|
7
|
+
The subject distance that fits a chart of a given physical size to the frame, with magnification, coverage and the minimum-focus check (2.3).
|
|
8
|
+
|
|
9
|
+
```ts
|
|
10
|
+
export function calculateSubjectDistanceForFraming(input: CalculateSubjectDistanceForFramingInput): SubjectFraming;
|
|
11
|
+
```
|
|
12
|
+
|
|
13
|
+
This call is synchronous; any supplied provider must follow its explicit synchronous contract.
|
|
14
|
+
|
|
15
|
+
## CalculateSubjectDistanceForFramingInput
|
|
16
|
+
|
|
17
|
+
The exact contract is declared below; use the domain guide for assumptions and staged integration.
|
|
18
|
+
|
|
19
|
+
```ts
|
|
20
|
+
export interface CalculateSubjectDistanceForFramingInput {
|
|
21
|
+
/** Active sensor (or simulated frame) size, mm. */
|
|
22
|
+
sensor: { widthMm: number; heightMm: number };
|
|
23
|
+
/** Physical focal length, mm. Give exactly one of this and `equivalentFocalLengthMm`. */
|
|
24
|
+
focalLengthMm?: number;
|
|
25
|
+
/** Full-frame-equivalent focal length (diagonal crop factor); a generic prime's value also reports that lens. */
|
|
26
|
+
equivalentFocalLengthMm?: number;
|
|
27
|
+
/** Chart size as for `simulateCapture` `chartSize`: heightM defaults to widthM × the sensor aspect (height / width). */
|
|
28
|
+
chart: { widthM: number; heightM?: number };
|
|
29
|
+
fit?: SubjectFramingFit;
|
|
30
|
+
}
|
|
31
|
+
```
|
|
32
|
+
|
|
33
|
+
## SubjectFraming
|
|
34
|
+
|
|
35
|
+
The exact contract is declared below; use the domain guide for assumptions and staged integration.
|
|
36
|
+
|
|
37
|
+
```ts
|
|
38
|
+
export interface SubjectFraming {
|
|
39
|
+
/** Distance from the lens to the chart plane, metres: f·(1 + 1/m). */
|
|
40
|
+
subjectDistanceM: number;
|
|
41
|
+
/** Image size ÷ object size, f/(d − f). */
|
|
42
|
+
magnification: number;
|
|
43
|
+
/** Thin-lens image distance f·(1 + m), mm. */
|
|
44
|
+
imageDistanceMm: number;
|
|
45
|
+
focalLengthMm: number;
|
|
46
|
+
equivalentFocalLengthMm: number;
|
|
47
|
+
cropFactor35Mm: number;
|
|
48
|
+
chart: { widthM: number; heightM: number };
|
|
49
|
+
fit: SubjectFramingFit;
|
|
50
|
+
/** Plane area the frame covers at that distance, metres. */
|
|
51
|
+
framedWidthM: number;
|
|
52
|
+
framedHeightM: number;
|
|
53
|
+
/** Fraction of the frame width and height the chart covers (1 on the fitted side; above 1 means cropped). */
|
|
54
|
+
coverage: { frameWidthFraction: number; frameHeightFraction: number };
|
|
55
|
+
/** The generic prime of this equivalent focal length, when there is one. */
|
|
56
|
+
prime: GenericPrimeLens | null;
|
|
57
|
+
/** The generic prime rule max(0.10 m, f·(1 + 1/0.15)) at this focal length (the prime's own value when there is one). */
|
|
58
|
+
minimumFocusDistanceM: number;
|
|
59
|
+
/** True when the fit distance is closer than the minimum focus distance: the chart cannot be framed this way. */
|
|
60
|
+
belowMinimumFocus: boolean;
|
|
61
|
+
scientificStatus: "approximation";
|
|
62
|
+
assumptions: readonly SimulateCaptureAssumption[];
|
|
63
|
+
}
|
|
64
|
+
```
|
|
65
|
+
|
|
66
|
+
## SubjectFramingFit
|
|
67
|
+
|
|
68
|
+
How the chart fits the frame: `contain` (default; the whole chart is visible and its limiting side touches the frame), `width`, `height` or `cover` (the chart fills the frame and is cropped on its other side).
|
|
69
|
+
|
|
70
|
+
```ts
|
|
71
|
+
export type SubjectFramingFit = "contain" | "width" | "height" | "cover";
|
|
72
|
+
```
|