@hatiolab/figure-model 0.1.76 → 0.1.78

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 (135) hide show
  1. package/CHANGELOG.md +12 -0
  2. package/README.md +60 -138
  3. package/dist/index.d.ts +1 -13
  4. package/dist/index.d.ts.map +1 -1
  5. package/dist/index.js +3 -26
  6. package/dist/index.js.map +1 -1
  7. package/dist/v3-asset-types.d.ts +1 -2
  8. package/dist/v3-asset-types.d.ts.map +1 -1
  9. package/dist/v3-asset.js +1 -1
  10. package/dist/v3-asset.js.map +1 -1
  11. package/dist/v3-authoring-actions.d.ts +9 -12
  12. package/dist/v3-authoring-actions.d.ts.map +1 -1
  13. package/dist/v3-authoring-actions.js +4 -5
  14. package/dist/v3-authoring-actions.js.map +1 -1
  15. package/dist/v3-capabilities.js +4 -1
  16. package/dist/v3-capabilities.js.map +1 -1
  17. package/dist/v3-cost.d.ts.map +1 -1
  18. package/dist/v3-cost.js +3 -5
  19. package/dist/v3-cost.js.map +1 -1
  20. package/dist/v3-create.d.ts +1 -1
  21. package/dist/v3-create.d.ts.map +1 -1
  22. package/dist/v3-examples.js +1 -1
  23. package/dist/v3-gate.d.ts +7 -8
  24. package/dist/v3-gate.d.ts.map +1 -1
  25. package/dist/v3-gate.js +11 -14
  26. package/dist/v3-gate.js.map +1 -1
  27. package/dist/v3-graph.d.ts +1 -2
  28. package/dist/v3-graph.d.ts.map +1 -1
  29. package/dist/v3-graph.js +5 -7
  30. package/dist/v3-graph.js.map +1 -1
  31. package/dist/v3-instance-size.d.ts +3 -5
  32. package/dist/v3-instance-size.d.ts.map +1 -1
  33. package/dist/v3-instance-size.js +2 -4
  34. package/dist/v3-instance-size.js.map +1 -1
  35. package/dist/v3-kernel-version.d.ts +1 -1
  36. package/dist/v3-kernel-version.js +1 -1
  37. package/dist/v3-part-edit.d.ts +4 -5
  38. package/dist/v3-part-edit.d.ts.map +1 -1
  39. package/dist/v3-part-edit.js +2 -2
  40. package/dist/v3-part-edit.js.map +1 -1
  41. package/dist/v3-proposal.js +1 -1
  42. package/dist/v3-proposal.js.map +1 -1
  43. package/dist/v3-release-contract.js +1 -1
  44. package/dist/v3-release-contract.js.map +1 -1
  45. package/dist/v3-score.d.ts +4 -5
  46. package/dist/v3-score.d.ts.map +1 -1
  47. package/dist/v3-score.js +7 -8
  48. package/dist/v3-score.js.map +1 -1
  49. package/dist/v3-words.d.ts +105 -0
  50. package/dist/v3-words.d.ts.map +1 -0
  51. package/dist/v3-words.js +107 -0
  52. package/dist/v3-words.js.map +1 -0
  53. package/docs/assembly-constraints-v3.md +13 -23
  54. package/docs/v3-asset-persistence.md +4 -4
  55. package/docs/v3-common-kernel-experiment.md +1 -1
  56. package/docs/v3-core-semantics.md +3 -3
  57. package/docs/v3-cutover.md +5 -3
  58. package/docs/v3-design.md +13 -26
  59. package/docs/v3-editor-integration.md +2 -2
  60. package/docs/v3-full-conveyor-validation.md +3 -3
  61. package/docs/v3-layout-system.md +1 -1
  62. package/docs/v3-minimal-model.md +0 -1
  63. package/docs/v3-motion-contract.md +21 -56
  64. package/docs/v3-runtime-extraction.md +7 -7
  65. package/docs/v3-sample-validation-expanded.md +1 -1
  66. package/docs/v3-sample-validation.md +1 -1
  67. package/docs/v3-shape-dimension-contract.md +23 -57
  68. package/docs/v3-status.md +5 -5
  69. package/docs/v3-storage-integration.md +4 -4
  70. package/package.json +2 -20
  71. package/dist/blueprint-shape.d.ts +0 -10
  72. package/dist/blueprint-shape.d.ts.map +0 -1
  73. package/dist/blueprint-shape.js +0 -194
  74. package/dist/blueprint-shape.js.map +0 -1
  75. package/dist/blueprint.d.ts +0 -73
  76. package/dist/blueprint.d.ts.map +0 -1
  77. package/dist/blueprint.js +0 -388
  78. package/dist/blueprint.js.map +0 -1
  79. package/dist/cost-chart.d.ts +0 -35
  80. package/dist/cost-chart.d.ts.map +0 -1
  81. package/dist/cost-chart.js +0 -150
  82. package/dist/cost-chart.js.map +0 -1
  83. package/dist/cost.d.ts +0 -162
  84. package/dist/cost.d.ts.map +0 -1
  85. package/dist/cost.js +0 -194
  86. package/dist/cost.js.map +0 -1
  87. package/dist/gate.d.ts +0 -65
  88. package/dist/gate.d.ts.map +0 -1
  89. package/dist/gate.js +0 -284
  90. package/dist/gate.js.map +0 -1
  91. package/dist/grouping.d.ts +0 -121
  92. package/dist/grouping.d.ts.map +0 -1
  93. package/dist/grouping.js +0 -224
  94. package/dist/grouping.js.map +0 -1
  95. package/dist/keys.d.ts +0 -45
  96. package/dist/keys.d.ts.map +0 -1
  97. package/dist/keys.js +0 -84
  98. package/dist/keys.js.map +0 -1
  99. package/dist/origin.d.ts +0 -33
  100. package/dist/origin.d.ts.map +0 -1
  101. package/dist/origin.js +0 -46
  102. package/dist/origin.js.map +0 -1
  103. package/dist/release-contract.d.ts +0 -38
  104. package/dist/release-contract.d.ts.map +0 -1
  105. package/dist/release-contract.js +0 -246
  106. package/dist/release-contract.js.map +0 -1
  107. package/dist/sizing.d.ts +0 -231
  108. package/dist/sizing.d.ts.map +0 -1
  109. package/dist/sizing.js +0 -550
  110. package/dist/sizing.js.map +0 -1
  111. package/dist/types.d.ts +0 -1233
  112. package/dist/types.d.ts.map +0 -1
  113. package/dist/types.js +0 -547
  114. package/dist/types.js.map +0 -1
  115. package/dist/v3-from-v2.d.ts +0 -203
  116. package/dist/v3-from-v2.d.ts.map +0 -1
  117. package/dist/v3-from-v2.js +0 -2053
  118. package/dist/v3-from-v2.js.map +0 -1
  119. package/dist/v3-mesh-compare.d.ts +0 -24
  120. package/dist/v3-mesh-compare.d.ts.map +0 -1
  121. package/dist/v3-mesh-compare.js +0 -55
  122. package/dist/v3-mesh-compare.js.map +0 -1
  123. package/dist/validate.d.ts +0 -7
  124. package/dist/validate.d.ts.map +0 -1
  125. package/dist/validate.js +0 -1119
  126. package/dist/validate.js.map +0 -1
  127. package/dist/visual-evidence.d.ts +0 -21
  128. package/dist/visual-evidence.d.ts.map +0 -1
  129. package/dist/visual-evidence.js +0 -52
  130. package/dist/visual-evidence.js.map +0 -1
  131. package/docs/design.md +0 -193
  132. package/docs/format-survey.md +0 -108
  133. package/docs/format.md +0 -704
  134. package/docs/sizing.md +0 -183
  135. package/docs/validation.md +0 -357
package/dist/sizing.js DELETED
@@ -1,550 +0,0 @@
1
- /*
2
- * Copyright © HatioLab Inc. All rights reserved.
3
- */
4
- /*
5
- * 이 파일은 things-scene 에서 왔다(2026-09-09).
6
- *
7
- * ## 왜 형식이 이것을 갖나
8
- *
9
- * `anchor` 가 무엇을 뜻하는지는 **형식의 의미**다. 그리는 쪽(things-scene)만 알고 있으면 형식을
10
- * 읽는 다른 쪽 — 발행 게이트가 「이 도형이 2배로 커져도 조각이 흩어지지 않나」를 물을 때 —
11
- * 같은 계산을 다시 적게 된다. 두 벌이 되면 한쪽만 고쳐지고, 그때 화면과 게이트가 다른 답을 낸다.
12
- *
13
- * things-scene 의 `figure-blueprint.ts` 가 이미 그 판단을 적어 두었다 — 「청사진의 형태를 확인하는
14
- * 일도 형식이 안다」. 사이징도 같은 자리다. 그리는 쪽은 이제 여기서 받아 쓴다.
15
- */
16
- import { DEFAULT_SIZING } from "./types.js";
17
- import { centredPart } from "./origin.js";
18
- /**
19
- * 인스턴스 크기가 바뀔 때 부품이 어떻게 반응하나.
20
- *
21
- * ## 왜 따로 떼어 두나
22
- *
23
- * 같은 답을 세 곳이 낸다 — 3D(`figure-real-object`), 2D 톱뷰(`figure-instance`),
24
- * 그리고 속성 편집기. 저마다 계산하면 화면마다 다른 모양이 나오고, 그때는 어느 쪽이
25
- * 맞는지 알 방법이 없다.
26
- *
27
- * ## 규칙 넷
28
- *
29
- * scale 비례 확대. 인스턴스 배율을 그대로 받는다 — 아무것도 하지 않아도 된다
30
- * fixed 크기는 그대로. **붙잡은 자리에서 잰 거리**를 지킨다
31
- * stretch 가장 길게 뻗은 축이 **양쪽 면 사이를 채운다**
32
- * repeat 크기는 그대로 두고 **개수**가 늘어난다
33
- *
34
- * ## 자리도 규칙의 일부다
35
- *
36
- * 한동안 이 파일은 **크기**만 다뤘고 자리는 언제나 비례였다. 그래서 시그널 타워를
37
- * 3 배로 세우면 기둥은 늘어나는데 램프들은 기둥 위 공중으로 흩어졌다.
38
- *
39
- * 1× foot 0..90 · pole 85..705 · bracket 703..747 · cap 1037..1087
40
- * 3× foot 90..180 · pole 255..2115 · bracket 2153..2197 · cap 3161..3211
41
- *
42
- * 램프는 상자 안 어디쯤이 아니라 **기둥 꼭대기**에 붙어 있다. 그 말을 하는 것이
43
- * 앵커다 — 부품이 어느 면에서 잰 거리를 지키는가.
44
- *
45
- * 세 가지가 한 규칙의 세 경우다. 축마다
46
- *
47
- * 아무 데도 안 붙잡는다 비례로 따라간다 `scale`
48
- * 한 자리를 붙잡는다 거기서 잰 거리 유지 `fixed` · `repeat` 의 옆 축
49
- * 두 면을 다 붙잡는다 가운데가 늘어나 채운다 `stretch` 의 긴 축
50
- *
51
- * 붙잡는 자리는 아래 면(`min`) · 가운데(`center`) · 위 면(`max`) 셋이다. 셋이 같은
52
- * 규칙이다 — 기준이 어디냐만 다르다. 한동안 `center` 만 「비례로 밀린다」였는데, 그러면
53
- * 가운데 가까이 저작한 것이 상자가 커질 때마다 밖으로 밀려 이웃과 갈라진다. 크레들의
54
- * V 홈 패드 둘이 ±80 에서 ±240 으로 벌어져 축을 놓친 것이 그것이었다.
55
- *
56
- * 3D 도구의 나인슬라이스가 하는 일과 같고, 여기서는 그것이 세 축으로 있다.
57
- *
58
- * ## 어떻게 되돌리나
59
- *
60
- * 부모(`object3d`)가 인스턴스 배율 `S` 를 이미 걸고 있다. 그래서 크기를 그대로 두려면
61
- * 자식이 `1/S` 로 되돌리면 된다. 자리는 부모의 배율을 그대로 받으므로 따라간다.
62
- *
63
- * 월드 = S · (자리 + (1/S) ⊙ 형상) = S·자리 + 형상
64
- *
65
- * 회전은 **형상에 미리 구워** 둔다. 그래야 위 식이 정확히 성립한다 — 회전을 mesh 에
66
- * 걸면 비균등 배율이 회전 뒤에 곱해져 형상이 기울어진다.
67
- *
68
- * 이 방식의 값은 **geometry 를 그대로 나눠 쓴다**는 것이다. 인스턴스가 몇이든 정점
69
- * 버퍼는 늘지 않는다. 대신 합칠 수 없어 draw call 이 부품 수만큼 는다 — 그 비용은
70
- * 청사진의 묶음 수에 그대로 잡히고 성숙도가 잰다.
71
- */
72
- /**
73
- * 이 축에서 이 부품이 어떻게 서나. **크기와 자리를 함께 정하는 한 값이다.**
74
- *
75
- * 저작자가 적었으면 그것이 이기고, 없으면 `sizing` 이 정한다.
76
- *
77
- * fixed 가까운 면
78
- * stretch 가장 긴 축은 `span`, 나머지는 가까운 면
79
- * repeat 늘어나는 축은 `center`(줄이 제자리에 남는다), 나머지는 가까운 면
80
- *
81
- * **가까운 면**은 상자의 위 절반에 저작한 것은 위를, 아래 절반은 아래를 붙잡는 것이다.
82
- * 사람이 램프를 꼭대기 근처에 놓을 때 뜻하는 것이 그것이다. 정확히 가운데면 `center` 이고,
83
- * 그때는 비례로 따라가는 것이 맞다 — 어느 쪽도 더 가깝지 않기 때문이다.
84
- *
85
- * 세는 것은 **부품의 면에서 상자의 면까지**이지 중심에서가 아니다. 중심으로 재면
86
- * 굵은 부품과 얇은 부품이 같은 자리에서 다른 답을 낸다.
87
- */
88
- /**
89
- * 저작면이 묻는 자리 — **부품 하나로 답한다.**
90
- *
91
- * `anchorOf` 는 `SizingSubject` 를 받는다. 그런데 이 값을 **보여 줘야 하는 곳**은 저작면이고,
92
- * 거기에는 청사진이 없다(편집 중인 `FigurePart` 만 있다). 그 자리가 규칙을 다시 쓰면 화면이
93
- * 말하는 붙잡는 면과 실제로 그려지는 것이 갈린다 — 규칙은 한 벌이어야 한다.
94
- *
95
- * 부품은 `sizing` 하나만 채우면 그 모양이 된다. 청사진에만 있는 칸(`geometryKey` · `triangles`)은
96
- * 셈이 보지 않는다 — 그 사실이 어긋나면 아래 시험이 깨진다(`gate.test.ts`: 부품과 청사진이 같은 답).
97
- */
98
- export function anchorOfPart(part, base, axis) {
99
- /*
100
- **기본값도 청사진과 같게 채운다.** 부품의 `sizing` 은 안 적을 수 있고 청사진은 그때
101
- `DEFAULT_SIZING` 을 채운다. 그것을 빼먹으면 같은 부품이 저작면에서 center, 그려질 때는
102
- scale 이 된다 — 시험이 그 자리에서 깨졌다.
103
- */
104
- /* The part comes from a source, so it is measured from the bottom face; the rule reads centred positions. */
105
- return anchorOf(centredPart({ ...part, sizing: part.sizing ?? DEFAULT_SIZING }, base), base, axis);
106
- }
107
- /**
108
- * 저작면이 묻는 개수 — **부품 하나로 답한다.**
109
- *
110
- * `anchorOfPart` 와 같은 자리다. 저작면에는 청사진이 없고 편집 중인 부품만 있는데, 「피치를
111
- * 이렇게 두면 몇 개가 되나」는 화면이 보여 줘야 하는 값이다. 그 자리가 개수를 다시 계산하면
112
- * 화면이 말하는 개수와 실제로 그려지는 개수가 달라진다.
113
- *
114
- * 기본값도 청사진과 같게 채운다 — 부품의 `sizing` 은 안 적을 수 있고 청사진은 그때
115
- * `DEFAULT_SIZING` 을 채운다.
116
- */
117
- export function repeatPlanOfPart(part, scale, base) {
118
- return repeatPlan(centredPart({ ...part, sizing: part.sizing ?? DEFAULT_SIZING }, base), scale, base);
119
- }
120
- export function anchorOf(member, base, axis) {
121
- const said = member.anchor?.[axis];
122
- if (said)
123
- return said;
124
- if (member.sizing === 'scale')
125
- return 'scale';
126
- if (member.sizing === 'stretch' && axis === stretchAxis(member))
127
- return 'span';
128
- if (member.sizing === 'repeat' && axis === member.repeat?.axis)
129
- return 'center';
130
- const gaps = clearance(member, base, axis);
131
- if (gaps.min < gaps.max)
132
- return 'min';
133
- if (gaps.max < gaps.min)
134
- return 'max';
135
- return 'center';
136
- }
137
- /**
138
- * 부품의 면에서 상자의 면까지 — 지켜야 할 거리 둘.
139
- *
140
- * Exported for the V2 → V3 converter, which writes these two distances into the V3 graph as constants.
141
- */
142
- export function clearance(member, base, axis) {
143
- const half = (Number.isFinite(base[axis]) ? base[axis] : 0) / 2;
144
- const at = member.transform.position[axis];
145
- const reach = rotatedExtent(member)[axis] / 2;
146
- return { min: at - reach + half, max: half - (at + reach) };
147
- }
148
- /** 0 이나 음수 배율을 그대로 쓰지 않는다 — 막 놓은 인스턴스가 실제로 0 이다. */
149
- function safeScale(value) {
150
- return Number.isFinite(value) && value > 0 ? value : 1;
151
- }
152
- /**
153
- * 늘어나는 축이 실제로 차지할 길이.
154
- *
155
- * 양쪽 여유를 지키고 가운데가 남는 만큼을 먹는다. 저작할 때의 여유가 그대로 남으므로
156
- * 기둥이 발판과 브래킷 **사이**를 정확히 잇는다.
157
- *
158
- * 상자가 여유 둘을 합친 것보다 작아지면 남는 것이 없다. 그때는 0 이 아니라 실오라기를
159
- * 남긴다 — 배율 0 인 mesh 는 법선 행렬이 특이해져 조명이 NaN 이 된다.
160
- */
161
- function spanLength(member, scale, base, axis) {
162
- const gaps = clearance(member, base, axis);
163
- const room = (Number.isFinite(base[axis]) ? base[axis] : 0) * safeScale(scale[axis]);
164
- return Math.max(room - gaps.min - gaps.max, SLIVER);
165
- }
166
- /** 사라지지 않을 만큼. 위 주석 참고. */
167
- const SLIVER = 1e-3;
168
- /**
169
- * 되돌릴 것이 있는 부품인가.
170
- *
171
- * `scale` 은 부모 배율을 그대로 받으면 되므로 합쳐 둔 채로 그린다. 나머지 셋은 따로
172
- * 세운다.
173
- *
174
- * **곡면은 `scale` 이어도 따로 선다.** 합친 형상은 변환을 하나만 받는데, 인스턴스가
175
- * 축마다 다른 배율이면 그 하나가 원기둥을 타원 기둥으로 만든다. 원기둥이라고 적어
176
- * 놓고 원기둥이 아닌 것을 그리게 된다.
177
- *
178
- * 값이 있는 만큼 값을 치른다 — 곡면 부품 하나가 draw call 하나다. figure-model 의
179
- * `standsAlone` 이 **같은 답**을 내야 한다. 갈리면 성숙도가 세는 수와 화면이 그리는
180
- * 수가 달라진다.
181
- */
182
- export function needsOwnMesh(member) {
183
- return member.sizing !== 'scale' || isCurved(member);
184
- }
185
- /**
186
- * 단면을 원으로 지키는 부품인가.
187
- *
188
- * 곡면만 지킬 수 있고, 저작자가 끄지 않는 한 지킨다. 끄면 합친 묶음에 들어가 draw call
189
- * 을 아끼는 대신 인스턴스 배율대로 찌그러진다 — 볼트 머리처럼 아무도 안 볼 것에 쓴다.
190
- *
191
- * figure-model 의 `keepsRound` 와 **같은 답**을 내야 한다.
192
- */
193
- function isCurved(member) {
194
- if (member.primitive !== 'cylinder' && member.primitive !== 'sphere')
195
- return false;
196
- return member.keepRound !== false;
197
- }
198
- /**
199
- * 회전까지 반영한 부품의 축별 크기.
200
- *
201
- * 회전한 상자의 여덟 꼭짓점을 각 축에 내린 것 — 축에 맞춘 경계다. 회전 행렬은
202
- * `Rx·Ry·Rz` 이고 three 의 기본 Euler 순서('XYZ')와 같다. `memberGeometry` 가 같은
203
- * 순서로 돌리므로 여기만 다르면 답이 갈린다.
204
- *
205
- * figure-model 의 `rotatedExtentOf` 와 같은 식이다. 그쪽이 정본이고 여기는 읽는 쪽의
206
- * 사본이다 — 이 패키지는 figure-model 에 의존하지 않는다(`figure-blueprint.ts` 참고).
207
- */
208
- export function rotatedExtent(member) {
209
- const { size, rotation } = member.transform;
210
- if (!rotation)
211
- return { ...size };
212
- const rad = Math.PI / 180;
213
- const cx = Math.cos((rotation.x ?? 0) * rad);
214
- const sx = Math.sin((rotation.x ?? 0) * rad);
215
- const cy = Math.cos((rotation.y ?? 0) * rad);
216
- const sy = Math.sin((rotation.y ?? 0) * rad);
217
- const cz = Math.cos((rotation.z ?? 0) * rad);
218
- const sz = Math.sin((rotation.z ?? 0) * rad);
219
- const rows = [
220
- [cy * cz, -cy * sz, sy],
221
- [sx * sy * cz + cx * sz, -sx * sy * sz + cx * cz, -sx * cy],
222
- [-cx * sy * cz + sx * sz, cx * sy * sz + sx * cz, cx * cy]
223
- ];
224
- const along = (row) => Math.abs(row[0]) * size.x + Math.abs(row[1]) * size.y + Math.abs(row[2]) * size.z;
225
- return { x: along(rows[0]), y: along(rows[1]), z: along(rows[2]) };
226
- }
227
- /**
228
- * `stretch` 일 때 늘어나는 축 — **가장 길게 뻗은 축**이다.
229
- *
230
- * 형식에 축을 적는 자리가 없어서 크기에서 읽는다. 프레임 · 벨트 · 레일이 전부 "길어서
231
- * 그 물건인 것"이라 이 규칙과 맞는다. 같으면 x → z → y 순으로 정한다.
232
- */
233
- export function stretchAxis(member) {
234
- const { x, y, z } = rotatedExtent(member);
235
- if (x >= z && x >= y)
236
- return 'x';
237
- if (z >= y)
238
- return 'z';
239
- return 'y';
240
- }
241
- /**
242
- * 부품 mesh 에 걸 배율 — 부모가 건 인스턴스 배율을 **어디까지 되돌릴까**.
243
- *
244
- * `1` 은 인스턴스를 그대로 따라간다는 뜻이고, `1/S` 는 저작한 크기를 지킨다는 뜻이다.
245
- *
246
- * `repeat` 는 부품 자체의 크기를 지킨다 — 늘어나는 것은 개수다.
247
- */
248
- export function sizingScale(member, scale, base) {
249
- /*
250
- **규칙은 축마다 정해진다.** 그것을 먼저 받아 둔다.
251
-
252
- 한동안 이 자리에 `if (member.sizing === 'scale') return flat` 이 있었다. `sizing` 이 없으면
253
- 컴파일이 그 값을 `'scale'` 로 채우므로, **`anchor` 만 적은 부품은 여기서 통째로 빠져나가
254
- 앵커가 조용히 무시되었다** — 크기도 자리도 비례로만 움직였다. 표본들이 `sizing` 을 쓰고
255
- 있어서 여태 드러나지 않았고, 발행 게이트를 만들며 `anchor` 만 쓴 시험이 그것을 잡았다.
256
-
257
- `anchorOf` 가 이미 우선순위를 안다 — 저작자가 적은 `anchor` 가 이기고, 없으면 `sizing` 이
258
- 정한다. 그러니 판정은 그 함수에만 두고, 빠른 길은 **셋 다 `scale` 로 판정된 때**만 탄다.
259
- */
260
- const rules = { x: anchorOf(member, base, 'x'), y: anchorOf(member, base, 'y'), z: anchorOf(member, base, 'z') };
261
- if (AXES.every(axis => rules[axis] === 'scale')) {
262
- /*
263
- 비례 확대는 되돌릴 것이 없다 — **곡면이 아니면.** 곡면은 축마다 다른 배율을 받으면
264
- 단면이 타원이 되므로 그때는 되돌린다.
265
-
266
- 3D 는 이 함수를 비-`scale` 부품에만 부르지만 2D 는 **모든 부품에** 부른다. 여기서
267
- 걸러 두지 않으면 평범한 부품까지 1/S 로 되돌아가 인스턴스를 키워도 그대로였다 —
268
- 시험이 그것을 잡았다.
269
- */
270
- const flat = { x: 1, y: 1, z: 1 };
271
- keepRound(member, scale, flat);
272
- return flat;
273
- }
274
- const undo = { x: safeUndo(scale.x), y: safeUndo(scale.y), z: safeUndo(scale.z) };
275
- for (const axis of AXES) {
276
- const rule = rules[axis];
277
- // 아무 면도 안 붙잡는 축은 부모가 건 배율을 그대로 받는다 — 되돌릴 것이 없다.
278
- if (rule === 'scale')
279
- undo[axis] = 1;
280
- if (rule !== 'span')
281
- continue;
282
- /*
283
- 양쪽을 다 붙잡은 축은 **여유를 지키고 남는 만큼**을 먹는다. 인스턴스 배율을 그대로
284
- 받게 두면(전에 `stretch` 가 그랬다) 기둥이 상자와 같은 비율로만 자라서, 끝에 붙여
285
- 둔 부품과의 사이에 틈이 벌어진다.
286
-
287
- 부모가 이미 `S` 를 걸고 있으므로 여기서는 원하는 총 배율을 `S` 로 나눠 넘긴다.
288
- */
289
- const own = rotatedExtent(member)[axis];
290
- undo[axis] = own > 0 ? spanLength(member, scale, base, axis) / own / safeScale(scale[axis]) : 1;
291
- }
292
- keepRound(member, scale, undo);
293
- followAspect(member, base, scale, undo);
294
- return undo;
295
- }
296
- /**
297
- * 다른 축의 배율을 따라간다 — **비율을 지킨다.**
298
- *
299
- * 드라이룸의 출입구가 그렇다. 방을 키우면 문도 커지지만 문은 문이라 폭이 높이에
300
- * 비례해야 한다. `scale` 로 두면 폭이 제 축을 따라가므로, 방을 폭으로만 늘리면 문이
301
- * 넓어지기만 하고 높아지지 않는다.
302
- *
303
- * 가리킨 축이 **끝난 뒤의** 배율을 따른다 — 그 축이 `span` 이면 채운 만큼, `fixed` 면 1,
304
- * `scale` 이면 인스턴스 배율이다. 그래서 이 함수는 다른 규칙이 다 정해진 다음에 돈다.
305
- * 형식이 `aspect-` 가 또 다른 `aspect-` 를 가리키는 것을 막으므로 한 번만 돌면 된다.
306
- *
307
- * ## 상자로 자르지 않는다
308
- *
309
- * 한동안 저작할 때의 여유를 넘지 않게 잘랐다. 문이 방보다 넓어지는 것을 막으려던 것인데,
310
- * 그러면 **롤이 막힌다** — 크레들이 길어질 때 롤 지름이 폭을 따라 커지는 것이 이 규칙을
311
- * 쓰는 다른 절반이고, 지름은 기준 상자의 높이를 넘어서 자란다.
312
- *
313
- * 자르지 않는 이유는 기준 상자가 담장이 아니기 때문이다. 배치 비율의 분모이고, 넘는
314
- * 부품은 이미 있다(컨베이어의 발판이 상자보다 넓다).
315
- *
316
- * 대신 값이 있다. 이미 벽을 꽉 채운 문은 높이만 커진 방에서 벽보다 넓어진다 — 그것은
317
- * 규칙의 흠이 아니라 「벽을 꽉 채운 것이 비율을 지킬 수는 없다」는 기하다. 그런 부품은
318
- * 여유를 두고 저작하거나 `span` 으로 채운다.
319
- */
320
- function followAspect(member, base, scale, undo) {
321
- const settled = { x: safeScale(scale.x) * undo.x, y: safeScale(scale.y) * undo.y, z: safeScale(scale.z) * undo.z };
322
- for (const axis of AXES) {
323
- const named = aspectOf(anchorOf(member, base, axis));
324
- if (!named)
325
- continue;
326
- undo[axis] = settled[named] / safeScale(scale[axis]);
327
- }
328
- }
329
- /** `aspect-y` 처럼 적혀 있으면 가리킨 축, 아니면 null. */
330
- function aspectOf(rule) {
331
- if (rule === 'aspect-x')
332
- return 'x';
333
- if (rule === 'aspect-y')
334
- return 'y';
335
- if (rule === 'aspect-z')
336
- return 'z';
337
- return null;
338
- }
339
- /**
340
- * 곡면 프리미티브의 단면은 **원이다.**
341
- *
342
- * 축마다 다른 배율을 받으면 원기둥이 타원 기둥이 된다. 크레들을 3 배로 세웠더니 롤의
343
- * 지름이 세로로만 3 배가 되어 납작한 타원이 나왔다 — 원기둥이라고 적어 놓고 원기둥이
344
- * 아닌 것을 그린 것이다.
345
- *
346
- * 그래서 단면의 두 축은 **같은 배율**을 받는다. 두 배율의 **기하평균**이다.
347
- *
348
- * 작은 쪽을 쓰면 크기까지 얼어붙는다 — 한 축만 늘인 인스턴스에서 지름이 1 배로 묶여,
349
- * 형태가 아니라 크기를 지키게 된다. 큰 쪽을 쓰면 반대로 좁은 축에서 크게 뚫고 나간다.
350
- * 기하평균은 둘 다 따라가면서 원을 지키고, `effectiveDepth` 가 높이를 정할 때 쓰는 것과
351
- * 같은 셈이다 — 한 축만 늘여도 덜 왜곡된다.
352
- *
353
- * 좁은 축의 상자를 얼마간 넘을 수 있다. 기준 상자는 배치 비율의 분모이지 담장이 아니고,
354
- * 넘는 부품은 이미 있다(컨베이어의 발판이 상자보다 넓다).
355
- *
356
- * 축이 어느 쪽인지는 회전을 반영해 정한다. `CylinderGeometry` 의 축은 돌리기 전 y 이고,
357
- * 그것을 부품의 회전으로 옮긴 뒤 가장 큰 성분이 있는 축이 그 부품의 축이다. 구는 축이
358
- * 없으므로 세 축이 다 단면이다.
359
- *
360
- * `polygon` · `rect` 는 저작자가 점을 찍은 단면이라 건드리지 않는다. 타원으로 만들고
361
- * 싶으면 그것으로 만든다.
362
- */
363
- function keepRound(member, scale, undo) {
364
- if (!isCurved(member))
365
- return;
366
- const spin = member.primitive === 'sphere' ? null : longAxis(member);
367
- const across = AXES.filter(axis => axis !== spin);
368
- let product = 1;
369
- for (const axis of across)
370
- product *= safeScale(scale[axis]) * undo[axis];
371
- if (!(product > 0) || !Number.isFinite(product))
372
- return;
373
- const even = Math.pow(product, 1 / across.length);
374
- for (const axis of across)
375
- undo[axis] = even / safeScale(scale[axis]);
376
- }
377
- /** 원기둥의 축 — 돌리기 전 y 를 부품의 회전으로 옮겨 가장 크게 놓인 축. Exported for the V2 → V3 converter. */
378
- export function longAxis(member) {
379
- const rotation = member.transform.rotation;
380
- if (!rotation)
381
- return 'y';
382
- const rad = Math.PI / 180;
383
- const cx = Math.cos((rotation.x ?? 0) * rad);
384
- const sx = Math.sin((rotation.x ?? 0) * rad);
385
- const cy = Math.cos((rotation.y ?? 0) * rad);
386
- const cz = Math.cos((rotation.z ?? 0) * rad);
387
- const sz = Math.sin((rotation.z ?? 0) * rad);
388
- const sy = Math.sin((rotation.y ?? 0) * rad);
389
- // Rx·Ry·Rz 의 둘째 열 — (0, 1, 0) 이 어디로 가나.
390
- const moved = {
391
- x: -cy * sz,
392
- y: -sx * sy * sz + cx * cz,
393
- z: cx * sy * sz + sx * cz
394
- };
395
- const size = { x: Math.abs(moved.x), y: Math.abs(moved.y), z: Math.abs(moved.z) };
396
- if (size.x >= size.y && size.x >= size.z)
397
- return 'x';
398
- return size.z >= size.y ? 'z' : 'y';
399
- }
400
- /**
401
- * 부품을 놓을 자리 — **부모가 배율을 걸기 전의 자리**다.
402
- *
403
- * 부모(`object3d`)가 인스턴스 배율 `S` 를 걸므로, 월드에서 원하는 자리를 `S` 로 나눠
404
- * 돌려준다. 그래서 `S = 1` 이면 언제나 저작한 자리 그대로다 — 저작 화면에서 보던 것이
405
- * 인스턴스 배율 1 에서 그대로 선다.
406
- *
407
- * center 저작한 자리. 상자와 함께 비례로 밀린다
408
- * min 아래 면에서 잰 거리를 지킨다
409
- * max 위 면에서 잰 거리를 지킨다
410
- * stretch 양쪽을 다 지키므로 자리는 두 끝의 가운데다
411
- */
412
- export function sizingPosition(member, scale, base) {
413
- const { position } = member.transform;
414
- /*
415
- 같은 이유로 `sizing` 을 직접 보지 않는다(§`sizingScale`) — `anchor` 만 적은 부품이 여기서
416
- 빠져나가면 자리가 비례로만 밀려, 크기는 지켜지는데 자리는 안 지켜지는 반쪽이 된다.
417
- */
418
- const rules = { x: anchorOf(member, base, 'x'), y: anchorOf(member, base, 'y'), z: anchorOf(member, base, 'z') };
419
- if (AXES.every(axis => rules[axis] === 'scale'))
420
- return { ...position };
421
- const out = { ...position };
422
- // 비율을 따라가는 축이 있으면 그 축이 **끝낸** 배율이 필요하다.
423
- const sized = sizingScale(member, scale, base);
424
- const worldFactor = (axis) => safeScale(scale[axis]) * sized[axis];
425
- for (const axis of AXES) {
426
- const rule = rules[axis];
427
- // 붙잡지 않는 축만 부모의 배율에 자리를 맡긴다.
428
- if (rule === 'scale')
429
- continue;
430
- /*
431
- 비율을 따라가는 축은 자리도 따라간다. 문에 붙은 표시등이 문과 함께 커지면서 문의
432
- 같은 자리에 남아야 하고, 그것은 자리에도 같은 배율이 걸려야 성립한다.
433
- */
434
- const named = aspectOf(rule);
435
- if (named) {
436
- out[axis] = (position[axis] * worldFactor(named)) / safeScale(scale[axis]);
437
- continue;
438
- }
439
- const factor = safeScale(scale[axis]);
440
- const half = (Number.isFinite(base[axis]) ? base[axis] : 0) / 2;
441
- const gaps = clearance(member, base, axis);
442
- const reach = rotatedExtent(member)[axis] / 2;
443
- if (rule === 'span')
444
- out[axis] = (-half * factor + gaps.min + spanLength(member, scale, base, axis) / 2) / factor;
445
- else if (rule === 'min')
446
- out[axis] = (-half * factor + gaps.min + reach) / factor;
447
- else if (rule === 'max')
448
- out[axis] = (half * factor - gaps.max - reach) / factor;
449
- // center — 가운데에서 잰 거리를 지킨다. 부모가 배율을 걸므로 나눠서 넘긴다.
450
- else
451
- out[axis] = position[axis] / factor;
452
- }
453
- return out;
454
- }
455
- /**
456
- * Where a joint's origin sits at an instance scale, in the frame `sizingPosition` answers in: before the
457
- * parent applies the instance scale (ADR-0066 decision 3).
458
- *
459
- * The origin is a point fixed to the part it is attached to (the joint child's parent part), so it
460
- * follows that part under sizing: it moves with the part's seat and keeps its offset from the part's
461
- * centre at the part's own scale. With no parent part the origin hangs from the figure frame and only
462
- * the instance scale moves it, which is the rest position unchanged in this frame.
463
- *
464
- * Sizing is solved in the rest pose. The joint's own movement is applied afterwards, as a rigid
465
- * transform, so turning a child never shears it under a lopsided instance.
466
- */
467
- export function jointOriginPosition(joint, attach, scale, base) {
468
- const { origin } = joint;
469
- if (!attach)
470
- return { ...origin };
471
- const seat = sizingPosition(attach, scale, base);
472
- const own = sizingScale(attach, scale, base);
473
- const centre = attach.transform.position;
474
- return {
475
- x: seat.x + (origin.x - centre.x) * own.x,
476
- y: seat.y + (origin.y - centre.y) * own.y,
477
- z: seat.z + (origin.z - centre.z) * own.z
478
- };
479
- }
480
- const AXES = ['x', 'y', 'z'];
481
- /** 0 이나 음수로 나누지 않는다 — 인스턴스 크기가 0 인 순간이 실제로 있다(막 놓았을 때). */
482
- function safeUndo(value) {
483
- return Number.isFinite(value) && value > 0 ? 1 / value : 1;
484
- }
485
- /**
486
- * `repeat` 를 몇 개로 펼치나.
487
- *
488
- * **기준 상자를 한 칸씩 채운다.** 저작자는 **단위 하나**를 그리고, 런타임이 그 축의
489
- * 길이를 채운다. 3D 도구의 배열 변형이 "길이에 맞추기" 로 하는 일과 같다.
490
- *
491
- * 개수 = floor(기준 상자의 그 축 길이 × 인스턴스 배율 ÷ 한 칸)
492
- *
493
- * ## 한 칸은 **중심에서 다음 중심까지**다
494
- *
495
- * 부품 크기와 무관하다. 전에는 `부품 크기 + 틈` 으로 셌는데, 그러면 부품을 굵게 하거나
496
- * 돌릴 때마다 줄 전체가 다시 깔린다. 롤러를 30° 기울였더니 축 방향 경계상자가 96 에서
497
- * 343 으로 늘어 개수가 16 에서 6 으로 무너졌다. 기울어진 롤러 둘은 빗살처럼 나란히
498
- * 놓이므로 그렇게 벌릴 이유가 없는데도 그랬다.
499
- *
500
- * 이제 기울여도 개수가 그대로다. **기울인 채로 바짝 붙여 까는 것**이 표현된다.
501
- *
502
- * ## 왜 부품 크기가 아니라 기준 상자를 채우나
503
- *
504
- * 전에는 "그 부품이 `scale` 이었다면 차지했을 만큼" 을 채웠다. 지름 96 짜리 롤러는
505
- * 컨베이어를 3 배로 늘려도 288 밖에 안 되어 롤러가 한두 개 나온다. 2400 짜리 컨베이어에
506
- * 롤러 하나는 컨베이어가 아니다.
507
- *
508
- * 롤러는 일정한 간격으로 전 구간에 깔린다. 길이가 두 배면 롤러도 두 배다.
509
- */
510
- export function repeatPlan(member, scale, base) {
511
- if (member.sizing !== 'repeat' || !member.repeat)
512
- return null;
513
- const axis = member.repeat.axis;
514
- const pitch = member.repeat.pitch;
515
- if (!(Number.isFinite(pitch) && pitch > 0))
516
- return null;
517
- /*
518
- **줄이 늘어나나 커지나.**
519
-
520
- 같은 「반복」이 두 가지다. 컨베이어의 롤러는 길어지면 개수가 늘고 한 칸 간격은
521
- 그대로다. 셀트레이의 셀은 커지면 셀이 커지고 개수는 그대로다 — 개수는 그 트레이가
522
- 몇 셀짜리냐이지 화면에 얼마나 크게 그렸느냐가 아니다.
523
-
524
- 그 갈림을 이 축의 앵커가 말한다. `scale` 이면 저작한 상자만으로 세고, 늘어나는
525
- 일은 부모의 배율이 한다(그릇이 배율을 되돌리지 않으므로 간격도 크기도 함께 큰다).
526
- */
527
- const spreads = anchorOf(member, base, axis) !== 'scale';
528
- const factor = spreads && Number.isFinite(scale[axis]) && scale[axis] > 0 ? scale[axis] : 1;
529
- const room = (Number.isFinite(base[axis]) && base[axis] > 0 ? base[axis] : pitch) * factor;
530
- const count = Math.max(1, Math.min(REPEAT_LIMIT, Math.floor(room / pitch)));
531
- return { axis, count, pitch };
532
- }
533
- /**
534
- * 한 부품이 펼쳐질 수 있는 최대 개수.
535
- *
536
- * 복제본 하나가 draw call 하나다. 인스턴스를 아주 크게 늘리면 개수가 끝없이 늘어 한
537
- * 자산이 프레임을 다 먹는다. 그 지점에서는 이미 낱개를 셀 수 없으므로 더 늘려도 보이는
538
- * 것이 달라지지 않는다.
539
- */
540
- export const REPEAT_LIMIT = 100;
541
- /**
542
- * 복제본 하나의 자리 — 저작한 자리를 가운데 두고 양쪽으로 벌린다.
543
- *
544
- * 한쪽으로만 늘어놓으면 부품이 커질 때마다 한 방향으로 밀려서, 저작할 때 맞춰 둔 자리가
545
- * 어긋난다. 가운데를 지키면 대칭으로 놓은 것들이 계속 대칭이다.
546
- */
547
- export function repeatOffset(index, count, pitch) {
548
- return (index - (count - 1) / 2) * pitch;
549
- }
550
- //# sourceMappingURL=sizing.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"sizing.js","sourceRoot":"","sources":["../src/sizing.ts"],"names":[],"mappings":"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"}