scax-engine 0.1.7 → 0.2.0-beta.1

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.
@@ -1,8 +1,4 @@
1
- export { default as SCAXEngine } from "./scax-engine";
2
- export { SCAXEngineCore } from "./scax-engine";
3
- export type { SturmProfileWorldZBounds } from "./sturm/sturm";
4
1
  export { default as Ray } from "./ray/ray";
5
- export type { RayProps } from "./ray/ray";
6
- export type { AffinePair } from "./affine/affine";
7
- export type { EyeModel, PupilType, LightSourceConfig, LensConfig, EyeConfig, EyePowerInput, SCAXEngineProps, SCAxPower, AstigmatismSummaryItem, PrismSummaryItem, SimulationResultInfo, SimulateResult, AffineAnalysisResult, } from "./scax-engine";
2
+ export { default as SCAXEngine, SCAXEngineCore } from "./scax-engine";
3
+ export type { MeridianInfo, PrismPower, SCAXEngineProps, SCAXPower, SimulateResult, } from "./scax-engine";
8
4
  //# sourceMappingURL=index.d.ts.map
@@ -6,13 +6,34 @@ export declare const CHROMATIC_RED_COLOR = 16281969;
6
6
  /** 프라우호퍼 e선 (초록) */
7
7
  export declare const CHROMATIC_GREEN_NM = 546.07;
8
8
  export declare const CHROMATIC_GREEN_COLOR = 4906624;
9
+ export type LightSourcePose = {
10
+ position?: {
11
+ x?: number;
12
+ y?: number;
13
+ z?: number;
14
+ };
15
+ tilt?: {
16
+ x?: number;
17
+ y?: number;
18
+ };
19
+ };
9
20
  export declare class LightSource {
10
21
  protected rays: Ray[];
22
+ private sourcePosition;
23
+ private sourceRotationQuaternion;
24
+ private sourceRotationPivot;
11
25
  constructor();
12
26
  protected directionFromVergence(origin: Vector3, z: number, vergence: number): Vector3;
13
27
  protected createRayFromPoint(origin: Vector3, z: number, vergence: number): void;
14
28
  protected createChromaticRayFromPoint(origin: Vector3, z: number, vergence: number, line: "e" | "C", chromaticVergenceOffset?: number): void;
15
29
  addRay(ray: Ray): void;
30
+ protected configurePose(pose: LightSourcePose | undefined, pivotZ?: number): void;
31
+ private toFiniteNumber;
32
+ private getRayPoints;
33
+ private rotatePointAroundPivot;
34
+ private transformRayAroundPivot;
35
+ private translateRay;
36
+ private applyPoseToRay;
16
37
  emitRays(): Ray[];
17
38
  }
18
39
  export type GridLightSourceProps = {
@@ -21,7 +42,7 @@ export type GridLightSourceProps = {
21
42
  division: number;
22
43
  z: number;
23
44
  vergence: number;
24
- };
45
+ } & LightSourcePose;
25
46
  export declare class GridLightSource extends LightSource {
26
47
  private width;
27
48
  private height;
@@ -45,7 +66,7 @@ export type RadialLightSourceProps = {
45
66
  angle_division: number;
46
67
  z: number;
47
68
  vergence: number;
48
- };
69
+ } & LightSourcePose;
49
70
  export declare class RadialLightSource extends LightSource {
50
71
  private radius;
51
72
  private division;
@@ -0,0 +1,19 @@
1
+ import Ray from "../ray/ray";
2
+ export declare function normalizePrismDiopters(value: unknown): number;
3
+ export declare function normalizeAngle360Degrees(value: unknown): number;
4
+ /**
5
+ * 임상 프리즘 Base(Δ, 렌즈→각막 시점 °)를 내부 x/y 프리즘 벡터(Δ)로 변환합니다.
6
+ * `SCAXEngineCore`와 동일한 관례입니다.
7
+ */
8
+ export declare function prismVectorFromClinicalBase(prismDiopter: unknown, baseAngleDeg: unknown): {
9
+ x: number;
10
+ y: number;
11
+ };
12
+ /**
13
+ * 굴절 직후 광선에 프리즘 편향(소각 근사)을 적용합니다.
14
+ */
15
+ export declare function applyPrismVectorToRay(ray: Ray, prism: {
16
+ x: number;
17
+ y: number;
18
+ }): Ray;
19
+ //# sourceMappingURL=prism-on-ray.d.ts.map
@@ -0,0 +1,32 @@
1
+ import { Quaternion, Vector3 } from "three";
2
+ import Surface from "../../surfaces/surface";
3
+ /** 각막 기준 안구 회전점 z(mm). `SCAXEngineCore`와 동일. */
4
+ export declare const EYE_ROTATION_PIVOT_FROM_CORNEA_MM = 13;
5
+ /** eye 처방(Base) → 실제 안구 편향에 쓰는 역벡터(내부 x/y, Δ). */
6
+ export declare function eyePrismEffectVectorFromPrescription(p: unknown, p_ax: unknown): {
7
+ x: number;
8
+ y: number;
9
+ };
10
+ /**
11
+ * eye.p / eye.p_ax(임상 Base) 및 eye.tilt(°)로부터
12
+ * 안구 강체 회전 쿼터니언(Euler XYZ, z=0). 기존 configure 광선 피벗 회전과 동일.
13
+ */
14
+ export declare function eyePrismAndTiltToQuaternion(p: unknown, p_ax: unknown, tiltDeg: {
15
+ x: number;
16
+ y: number;
17
+ }): Quaternion;
18
+ export declare function eyeRotationPivot(): Vector3;
19
+ /** eye prism/tilt를 반영한 렌더용 각도(°). */
20
+ export declare function eyeRotationForRenderDegrees(p: unknown, p_ax: unknown, tiltDeg: {
21
+ x: number;
22
+ y: number;
23
+ }): {
24
+ x_deg: number;
25
+ y_deg: number;
26
+ magnitude_deg: number;
27
+ };
28
+ /**
29
+ * 안구 회전점 기준 강체 회전을 각 표면의 world `position` / `tilt`에 반영합니다.
30
+ */
31
+ export declare function applyRigidEyePoseToSurfaces(surfaces: Surface[], pivot: Vector3, rotation: Quaternion): void;
32
+ //# sourceMappingURL=eye-rigid-pose.d.ts.map
@@ -28,10 +28,33 @@ export interface EyeModelParameterConfig {
28
28
  origin?: string;
29
29
  surfaces: EyeSurfaceParameter[];
30
30
  }
31
+ /**
32
+ * `SCAXEngineCore.configure`와 동일한 눈 처방 필드.
33
+ * - `s,c,ax`: auto refractor(굴절오차) 기준; ST 면에는 보정렌즈 관점으로 변환되어 들어갑니다.
34
+ * - `p,p_ax,tilt`: 안구 회전점 기준 강체 pose로 각 표면 `position`/`tilt`에 전개됩니다.
35
+ */
36
+ export type EyeStackCreateInput = {
37
+ eyeModel: "gullstrand" | "navarro";
38
+ s: number;
39
+ c: number;
40
+ ax: number;
41
+ p?: number;
42
+ p_ax?: number;
43
+ tilt?: {
44
+ x?: number;
45
+ y?: number;
46
+ };
47
+ /** 0이면 동공 aperture 면을 넣지 않습니다. */
48
+ pupilDiameterMm: number;
49
+ };
31
50
  export declare class EyeModelParameter {
32
51
  private readonly parameter;
33
52
  constructor(parameter: EyeModelParameterConfig);
34
- createSurface(): Surface[];
53
+ /**
54
+ * 동공(선택) → eye_st(ST 복합면) → 안구 모델 해부면 순으로 생성한 뒤,
55
+ * `p`/`p_ax`/`tilt`를 안구 회전점 기준 강체 회전으로 반영합니다.
56
+ */
57
+ createSurface(eye: EyeStackCreateInput): Surface[];
35
58
  }
36
59
  export {};
37
60
  //# sourceMappingURL=eyemodel-parameter.d.ts.map
@@ -1,19 +1,27 @@
1
1
  import Affine from "./affine/affine";
2
2
  import { GridLightSourceProps, GridRGLightSourceProps, LightSource, RadialLightSourceProps } from "./light-sources/light-source";
3
+ import { EyeModelParameter } from "./parameters/eye/eyemodel-parameter";
3
4
  import Ray from "./ray/ray";
4
5
  import Surface from "./surfaces/surface";
5
6
  export type EyeModel = "gullstrand" | "navarro";
6
7
  export type PupilType = "constricted" | "neutral" | "dilated" | "none";
7
- export type LightSourceTransform = {
8
- position?: {
9
- x?: number;
10
- y?: number;
11
- z?: number;
12
- };
13
- tilt?: {
14
- x?: number;
15
- y?: number;
16
- };
8
+ type Position3D = {
9
+ x: number;
10
+ y: number;
11
+ z: number;
12
+ };
13
+ type Rotation2D = {
14
+ x: number;
15
+ y: number;
16
+ };
17
+ type PartialPosition3D = {
18
+ x?: number;
19
+ y?: number;
20
+ z?: number;
21
+ };
22
+ type PartialRotation2D = {
23
+ x?: number;
24
+ y?: number;
17
25
  };
18
26
  export type LightSourceConfig = ({
19
27
  type: "radial";
@@ -22,27 +30,26 @@ export type LightSourceConfig = ({
22
30
  } & GridLightSourceProps & LightSourceTransform) | ({
23
31
  type: "grid_rg";
24
32
  } & GridRGLightSourceProps & LightSourceTransform);
33
+ export type LightSourceTransform = {
34
+ position?: PartialPosition3D;
35
+ tilt?: PartialRotation2D;
36
+ };
37
+ type NormalizedLightSourceConfig = LightSourceConfig & {
38
+ position: Position3D;
39
+ tilt: Rotation2D;
40
+ };
25
41
  export type LensConfig = {
26
42
  s: number;
27
43
  c: number;
28
44
  ax: number;
29
45
  p?: number;
30
46
  p_ax?: number;
31
- position: {
32
- x: number;
33
- y: number;
34
- z: number;
35
- };
36
- tilt: {
37
- x: number;
38
- y: number;
39
- };
40
- /**
41
- * false이면 `simulate().info.astigmatism`의 `lens`·`combined` 파워 벡터 합에서 이 항목을 빼고,
42
- * 광선 추적·프리즘·Sturm 등은 그대로 적용합니다. (예: 시험용 JCC/크로스실린더)
43
- * @default true
44
- */
45
- includeInAstigmatismSummary?: boolean;
47
+ position: Position3D;
48
+ tilt: Rotation2D;
49
+ };
50
+ type NormalizedLensConfig = LensConfig & {
51
+ p: number;
52
+ p_ax: number;
46
53
  };
47
54
  export type EyeConfig = {
48
55
  s: number;
@@ -50,12 +57,13 @@ export type EyeConfig = {
50
57
  ax: number;
51
58
  p?: number;
52
59
  p_ax?: number;
53
- tilt?: {
54
- x?: number;
55
- y?: number;
56
- };
60
+ tilt?: PartialRotation2D;
61
+ };
62
+ type NormalizedEyeConfig = EyeConfig & {
63
+ p: number;
64
+ p_ax: number;
65
+ tilt: Rotation2D;
57
66
  };
58
- export type EyePowerInput = EyeConfig;
59
67
  export type SCAXEngineProps = {
60
68
  eyeModel?: EyeModel;
61
69
  eye?: EyeConfig;
@@ -63,56 +71,30 @@ export type SCAXEngineProps = {
63
71
  light_source?: LightSourceConfig;
64
72
  pupil_type?: PupilType;
65
73
  };
66
- export type SCAxPower = {
67
- s: number;
68
- c: number;
69
- ax: number;
74
+ type NormalizedEngineConfig = {
75
+ eyeModel: EyeModel;
76
+ eye: NormalizedEyeConfig;
77
+ lens: NormalizedLensConfig[];
78
+ light_source: NormalizedLightSourceConfig;
79
+ pupil_type: PupilType;
70
80
  };
81
+ export declare function normalizeEngineProps(props?: SCAXEngineProps): NormalizedEngineConfig;
71
82
  export type SimulateResult = {
72
83
  traced_rays: Ray[];
73
- info: SimulationResultInfo;
74
84
  };
75
- export type PrismVector = {
76
- x: number;
77
- y: number;
78
- magnitude: number;
79
- angle_deg: number;
85
+ export type PrismPower = {
86
+ p: number;
87
+ p_ax: number;
80
88
  };
81
- export type EyeRotationForRender = {
82
- x_deg: number;
83
- y_deg: number;
84
- magnitude_deg: number;
85
- };
86
- export type LightDeviation = {
87
- eye_prism_effect: PrismVector;
88
- lens_prism_total: PrismVector;
89
- net_prism: PrismVector;
90
- x_angle_deg: number;
91
- y_angle_deg: number;
92
- net_angle_deg: number;
89
+ export type SCAXPower = {
90
+ s: number;
91
+ c: number;
92
+ ax: number;
93
93
  };
94
- export type AstigmatismSummaryItem = {
94
+ export type MeridianInfo = {
95
95
  tabo: number;
96
96
  d: number;
97
97
  }[];
98
- export type PrismSummaryItem = {
99
- p_x: number;
100
- p_y: number;
101
- prism_angle: number;
102
- magnitude: number | null;
103
- };
104
- export type SimulationResultInfo = {
105
- astigmatism: {
106
- eye: AstigmatismSummaryItem;
107
- lens: AstigmatismSummaryItem;
108
- combined: AstigmatismSummaryItem;
109
- };
110
- prism: {
111
- eye: PrismSummaryItem;
112
- lens: PrismSummaryItem;
113
- combined: PrismSummaryItem;
114
- };
115
- };
116
98
  export type AffineAnalysisResult = ReturnType<Affine["estimate"]>;
117
99
  /**
118
100
  * legacy simulator.js를 TypeScript로 옮긴 핵심 시뮬레이터입니다.
@@ -121,43 +103,25 @@ export type AffineAnalysisResult = ReturnType<Affine["estimate"]>;
121
103
  * - Sturm 분석까지 제공합니다.
122
104
  */
123
105
  export declare class SCAXEngineCore {
124
- private static readonly EYE_ROTATION_PIVOT_FROM_CORNEA_MM;
125
- private eyeModel;
126
106
  private surfaces;
127
107
  private lens;
128
108
  private light_source;
129
- private eyeModelParameter;
109
+ private _eyeModelParameter;
130
110
  private tracedRays;
131
111
  private lastSourceRaysForSturm;
132
112
  private sturm;
133
113
  private affine;
134
114
  private lastSturmGapAnalysis;
135
115
  private lastAffineAnalysis;
136
- private pupilDiameterMm;
137
- private hasPupilStop;
138
- private eyePower;
139
- private lensConfigs;
140
- private lensPowers;
141
- private eyePrismEffectVector;
142
- private lensPrismVector;
143
- private eyePrismPrescription;
144
- private eyeRotationQuaternion;
145
- private eyeRotationQuaternionInverse;
146
- private eyeRotationPivot;
147
- private eyeTiltDeg;
148
- private lightSourcePosition;
149
- private lightSourceTiltDeg;
150
- private lightSourceRotationQuaternion;
151
- private lightSourceRotationPivot;
152
116
  private sortedLensSurfaces;
153
117
  private sortedEyeSurfaces;
154
- private currentProps;
155
- constructor(props?: SCAXEngineProps);
118
+ get eyeModelParameter(): EyeModelParameter;
119
+ constructor(config?: SCAXEngineProps | NormalizedEngineConfig);
156
120
  /**
157
121
  * 생성자와 동일한 기본값 규칙으로 광학 설정을 다시 적용합니다.
158
122
  * 생략한 최상위 필드는 매번 기본값으로 돌아갑니다(이전 값과 병합하지 않음).
159
123
  */
160
- update(props?: SCAXEngineProps): void;
124
+ update(config?: SCAXEngineProps | NormalizedEngineConfig): void;
161
125
  dispose(): void;
162
126
  private configure;
163
127
  /**
@@ -165,11 +129,6 @@ export declare class SCAXEngineCore {
165
129
  * includeSturmData 값과 무관하게 확장 분석(Sturm/retinaPairs)을 항상 포함합니다.
166
130
  */
167
131
  simulate(): SimulateResult;
168
- /**
169
- * eye.p / eye.p_ax(처방값)를 기준으로, 렌더링에서 바로 쓸 눈 회전량을 반환합니다.
170
- * - x_deg/y_deg는 프리즘 회전량에 eye.tilt를 합산한 최종 렌더 회전량입니다.
171
- */
172
- getEyeRotation(): EyeRotationForRender;
173
132
  /**
174
133
  * 1) Ray tracing 전용 함수
175
134
  * 광원에서 시작한 광선을 표면 순서대로 굴절시켜 최종 광선 집합을 반환합니다.
@@ -299,31 +258,8 @@ export declare class SCAXEngineCore {
299
258
  private surfaceOrderZ;
300
259
  private readSurfacePosition;
301
260
  private getRayPoints;
302
- private isRayInsidePupil;
303
261
  private powerVectorFromCylinder;
304
- private aggregatePowerVector;
305
- /** 난시 주경선 TABO 각도: 180° 동치이므로 표시·비교는 항상 [0, 180)으로 맞춘다. */
306
- private normalizeTaboMeridian180;
307
- private principalMeridiansFromVector;
308
- private astigmatismSummaryLensPowers;
309
- private principalMeridiansFromPowers;
310
- private normalizePrismAmount;
311
- private normalizeAngle360;
312
- private normalizeEyeTilt;
313
- private normalizeLightSourcePose;
314
- private toFiniteNumber;
315
262
  private refreshSortedSurfaces;
316
- private prismVectorFromBase;
317
- private vectorToPrismInfo;
318
- private toPrismSummaryItem;
319
- private prismComponentToAngleDeg;
320
- private prismMagnitudeToAngleDeg;
321
- private applyPrismVectorToRay;
322
- private rotatePointAroundPivot;
323
- private translateRay;
324
- private transformRayAroundPivot;
325
- private applyLightSourceTransformToRay;
326
- private calculateLightDeviation;
327
263
  private effectiveCylinderFromOpticSurfaces;
328
264
  private estimateAffineDistortion;
329
265
  private createAffinePairs;
@@ -334,6 +270,7 @@ export declare class SCAXEngineCore {
334
270
  */
335
271
  export default class SCAXEngine {
336
272
  private readonly core;
273
+ private normalizedConfig;
337
274
  constructor(props?: SCAXEngineProps);
338
275
  get lens(): Surface[];
339
276
  get light_source(): LightSource;
@@ -341,7 +278,6 @@ export default class SCAXEngine {
341
278
  update(props?: SCAXEngineProps): void;
342
279
  dispose(): void;
343
280
  simulate(): SimulateResult;
344
- getEyeRotation(): EyeRotationForRender;
345
281
  rayTracing(): Ray[];
346
282
  sturmCalculation(rays?: Ray[]): {
347
283
  slices_info: {
@@ -454,6 +390,11 @@ export default class SCAXEngine {
454
390
  };
455
391
  }[];
456
392
  };
457
- getAffineAnalysis(): AffineAnalysisResult;
393
+ calculateMeridians(scaxPowers: SCAXPower[]): MeridianInfo;
394
+ calculateEyeRotationByPrism(prism: PrismPower): {
395
+ x: number;
396
+ y: number;
397
+ };
458
398
  }
399
+ export {};
459
400
  //# sourceMappingURL=scax-engine.d.ts.map
@@ -1,4 +1,4 @@
1
- import { Vector3 } from "three";
1
+ import { Quaternion, Vector3 } from "three";
2
2
  import { RefractiveIndexSpec } from "../optics/refractive-index";
3
3
  import Ray from "../ray/ray";
4
4
  import Surface from "./surface";
@@ -28,6 +28,10 @@ export type STSurfaceProps = {
28
28
  z: number;
29
29
  };
30
30
  thickness?: number;
31
+ /** 임상 프리즘(Δ). 있으면 굴절 직후 광선에 적용합니다. */
32
+ p?: number;
33
+ /** 프리즘 Base 축(°, 렌즈→각막 시점). */
34
+ p_ax?: number;
31
35
  };
32
36
  export default class STSurface extends Surface {
33
37
  private static readonly POWER_EPS_D;
@@ -44,7 +48,9 @@ export default class STSurface extends Surface {
44
48
  private toricSurface;
45
49
  private sphericalRadiusMm;
46
50
  private toricRadiusPerpMm;
51
+ private readonly prismVector;
47
52
  constructor(props: STSurfaceProps);
53
+ private pushRefractedWithPrism;
48
54
  /**
49
55
  * 디옵터(D)로부터 반경(mm)을 계산합니다.
50
56
  *
@@ -88,5 +94,6 @@ export default class STSurface extends Surface {
88
94
  refract(ray: Ray): Ray | null;
89
95
  incident(ray: Ray): Vector3 | null;
90
96
  getOptimizedThicknessMm(): number;
97
+ applyRigidRotationAboutPivot(pivot: Vector3, rotation: Quaternion): void;
91
98
  }
92
99
  //# sourceMappingURL=st-surface.d.ts.map
@@ -1,4 +1,4 @@
1
- import { Vector2, Vector3 } from "three";
1
+ import { Quaternion, Vector2, Vector3 } from "three";
2
2
  import Ray from "../ray/ray";
3
3
  export type SurfaceProps = {
4
4
  type: string;
@@ -28,5 +28,11 @@ export default abstract class Surface {
28
28
  abstract incident(ray: Ray): Vector3 | null;
29
29
  abstract refract(ray: Ray): Ray | null;
30
30
  clearTraceHistory(): void;
31
+ getWorldPosition(): Vector3;
32
+ setPositionAndTilt(position: Vector3, tiltXDeg: number, tiltYDeg: number): void;
33
+ /**
34
+ * 안질 tilt가 0인 표면을 전제로, pivot 기준 강체 회전 후 동일 Euler(XYZ) tilt를 부여합니다.
35
+ */
36
+ applyRigidRotationAboutPivot(pivot: Vector3, rotation: Quaternion): void;
31
37
  }
32
38
  //# sourceMappingURL=surface.d.ts.map
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "scax-engine",
3
- "version": "0.1.7",
3
+ "version": "0.2.0-beta.1",
4
4
  "description": "Optical calculation engine for an eye model, with ESM, CJS, and UMD builds.",
5
5
  "main": "./dist/scax-engine.cjs",
6
6
  "module": "./dist/scax-engine.js",