@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.
- package/CHANGELOG.md +12 -0
- package/README.md +60 -138
- package/dist/index.d.ts +1 -13
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +3 -26
- package/dist/index.js.map +1 -1
- package/dist/v3-asset-types.d.ts +1 -2
- package/dist/v3-asset-types.d.ts.map +1 -1
- package/dist/v3-asset.js +1 -1
- package/dist/v3-asset.js.map +1 -1
- package/dist/v3-authoring-actions.d.ts +9 -12
- package/dist/v3-authoring-actions.d.ts.map +1 -1
- package/dist/v3-authoring-actions.js +4 -5
- package/dist/v3-authoring-actions.js.map +1 -1
- package/dist/v3-capabilities.js +4 -1
- package/dist/v3-capabilities.js.map +1 -1
- package/dist/v3-cost.d.ts.map +1 -1
- package/dist/v3-cost.js +3 -5
- package/dist/v3-cost.js.map +1 -1
- package/dist/v3-create.d.ts +1 -1
- package/dist/v3-create.d.ts.map +1 -1
- package/dist/v3-examples.js +1 -1
- package/dist/v3-gate.d.ts +7 -8
- package/dist/v3-gate.d.ts.map +1 -1
- package/dist/v3-gate.js +11 -14
- package/dist/v3-gate.js.map +1 -1
- package/dist/v3-graph.d.ts +1 -2
- package/dist/v3-graph.d.ts.map +1 -1
- package/dist/v3-graph.js +5 -7
- package/dist/v3-graph.js.map +1 -1
- package/dist/v3-instance-size.d.ts +3 -5
- package/dist/v3-instance-size.d.ts.map +1 -1
- package/dist/v3-instance-size.js +2 -4
- package/dist/v3-instance-size.js.map +1 -1
- package/dist/v3-kernel-version.d.ts +1 -1
- package/dist/v3-kernel-version.js +1 -1
- package/dist/v3-part-edit.d.ts +4 -5
- package/dist/v3-part-edit.d.ts.map +1 -1
- package/dist/v3-part-edit.js +2 -2
- package/dist/v3-part-edit.js.map +1 -1
- package/dist/v3-proposal.js +1 -1
- package/dist/v3-proposal.js.map +1 -1
- package/dist/v3-release-contract.js +1 -1
- package/dist/v3-release-contract.js.map +1 -1
- package/dist/v3-score.d.ts +4 -5
- package/dist/v3-score.d.ts.map +1 -1
- package/dist/v3-score.js +7 -8
- package/dist/v3-score.js.map +1 -1
- package/dist/v3-words.d.ts +105 -0
- package/dist/v3-words.d.ts.map +1 -0
- package/dist/v3-words.js +107 -0
- package/dist/v3-words.js.map +1 -0
- package/docs/assembly-constraints-v3.md +13 -23
- package/docs/v3-asset-persistence.md +4 -4
- package/docs/v3-common-kernel-experiment.md +1 -1
- package/docs/v3-core-semantics.md +3 -3
- package/docs/v3-cutover.md +5 -3
- package/docs/v3-design.md +13 -26
- package/docs/v3-editor-integration.md +2 -2
- package/docs/v3-full-conveyor-validation.md +3 -3
- package/docs/v3-layout-system.md +1 -1
- package/docs/v3-minimal-model.md +0 -1
- package/docs/v3-motion-contract.md +21 -56
- package/docs/v3-runtime-extraction.md +7 -7
- package/docs/v3-sample-validation-expanded.md +1 -1
- package/docs/v3-sample-validation.md +1 -1
- package/docs/v3-shape-dimension-contract.md +23 -57
- package/docs/v3-status.md +5 -5
- package/docs/v3-storage-integration.md +4 -4
- package/package.json +2 -20
- package/dist/blueprint-shape.d.ts +0 -10
- package/dist/blueprint-shape.d.ts.map +0 -1
- package/dist/blueprint-shape.js +0 -194
- package/dist/blueprint-shape.js.map +0 -1
- package/dist/blueprint.d.ts +0 -73
- package/dist/blueprint.d.ts.map +0 -1
- package/dist/blueprint.js +0 -388
- package/dist/blueprint.js.map +0 -1
- package/dist/cost-chart.d.ts +0 -35
- package/dist/cost-chart.d.ts.map +0 -1
- package/dist/cost-chart.js +0 -150
- package/dist/cost-chart.js.map +0 -1
- package/dist/cost.d.ts +0 -162
- package/dist/cost.d.ts.map +0 -1
- package/dist/cost.js +0 -194
- package/dist/cost.js.map +0 -1
- package/dist/gate.d.ts +0 -65
- package/dist/gate.d.ts.map +0 -1
- package/dist/gate.js +0 -284
- package/dist/gate.js.map +0 -1
- package/dist/grouping.d.ts +0 -121
- package/dist/grouping.d.ts.map +0 -1
- package/dist/grouping.js +0 -224
- package/dist/grouping.js.map +0 -1
- package/dist/keys.d.ts +0 -45
- package/dist/keys.d.ts.map +0 -1
- package/dist/keys.js +0 -84
- package/dist/keys.js.map +0 -1
- package/dist/origin.d.ts +0 -33
- package/dist/origin.d.ts.map +0 -1
- package/dist/origin.js +0 -46
- package/dist/origin.js.map +0 -1
- package/dist/release-contract.d.ts +0 -38
- package/dist/release-contract.d.ts.map +0 -1
- package/dist/release-contract.js +0 -246
- package/dist/release-contract.js.map +0 -1
- package/dist/sizing.d.ts +0 -231
- package/dist/sizing.d.ts.map +0 -1
- package/dist/sizing.js +0 -550
- package/dist/sizing.js.map +0 -1
- package/dist/types.d.ts +0 -1233
- package/dist/types.d.ts.map +0 -1
- package/dist/types.js +0 -547
- package/dist/types.js.map +0 -1
- package/dist/v3-from-v2.d.ts +0 -203
- package/dist/v3-from-v2.d.ts.map +0 -1
- package/dist/v3-from-v2.js +0 -2053
- package/dist/v3-from-v2.js.map +0 -1
- package/dist/v3-mesh-compare.d.ts +0 -24
- package/dist/v3-mesh-compare.d.ts.map +0 -1
- package/dist/v3-mesh-compare.js +0 -55
- package/dist/v3-mesh-compare.js.map +0 -1
- package/dist/validate.d.ts +0 -7
- package/dist/validate.d.ts.map +0 -1
- package/dist/validate.js +0 -1119
- package/dist/validate.js.map +0 -1
- package/dist/visual-evidence.d.ts +0 -21
- package/dist/visual-evidence.d.ts.map +0 -1
- package/dist/visual-evidence.js +0 -52
- package/dist/visual-evidence.js.map +0 -1
- package/docs/design.md +0 -193
- package/docs/format-survey.md +0 -108
- package/docs/format.md +0 -704
- package/docs/sizing.md +0 -183
- package/docs/validation.md +0 -357
package/dist/gate.js
DELETED
|
@@ -1,284 +0,0 @@
|
|
|
1
|
-
import { compile } from "./blueprint.js";
|
|
2
|
-
import { rotatedExtentOf } from "./blueprint.js";
|
|
3
|
-
import { anchorOf, sizingPosition, sizingScale } from "./sizing.js";
|
|
4
|
-
import { SKIN } from "./types.js";
|
|
5
|
-
/*
|
|
6
|
-
* 발행해도 되나 — **크기를 바꿔 봐야 알 수 있는 것들.**
|
|
7
|
-
*
|
|
8
|
-
* ## 왜 형식이 이것을 재나
|
|
9
|
-
*
|
|
10
|
-
* 이 검사는 브라우저 하네스에만 있었다(things-factory `test/browser/check-figure-scaling.mjs`). 그
|
|
11
|
-
* 자리에서는 사람이 돌릴 때만 돌고, 서버는 같은 질문에 답할 방법이 없어 **아무 검사 없이 발행이
|
|
12
|
-
* 되었다.** 앵커의 뜻을 아는 것이 형식이므로(`sizing.ts`), 그 뜻이 실제로 성립하는지도 형식이 잰다.
|
|
13
|
-
*
|
|
14
|
-
* ## 무엇을 재나
|
|
15
|
-
*
|
|
16
|
-
* **덩어리가 늘어나지 않는가.** 도형은 서로 닿아 한 덩어리여야 한다. 크기를 바꿨을 때 조각이 갈라
|
|
17
|
-
* 지면 사람 눈에 「부서졌다」로 보인다 — 시그널타워를 3배로 세우니 램프가 기둥 위 공중에 뜬 것이
|
|
18
|
-
* 그것이었고, 앵커 규칙이 생긴 이유다.
|
|
19
|
-
*
|
|
20
|
-
* 축을 하나씩만 늘리는 것으로는 부족하다. x 만 늘려서 멀쩡한 것이 x·z 를 함께 늘리면 갈라진다 —
|
|
21
|
-
* `aspect-` 처럼 다른 축을 보는 규칙이 있어서다. 그래서 **일곱 조합**을 전부 본다.
|
|
22
|
-
*/
|
|
23
|
-
/** 크기를 바꿔 보는 일곱 가지. 축 하나씩 셋, 둘씩 셋, 셋 한꺼번에. */
|
|
24
|
-
export const SIZING_WAYS = [
|
|
25
|
-
{ name: 'x', axes: ['x'] },
|
|
26
|
-
{ name: 'y', axes: ['y'] },
|
|
27
|
-
{ name: 'z', axes: ['z'] },
|
|
28
|
-
{ name: 'x-y', axes: ['x', 'y'] },
|
|
29
|
-
{ name: 'x-z', axes: ['x', 'z'] },
|
|
30
|
-
{ name: 'y-z', axes: ['y', 'z'] },
|
|
31
|
-
{ name: 'x-y-z', axes: ['x', 'y', 'z'] }
|
|
32
|
-
];
|
|
33
|
-
/** 몇 배로 재나. 2배면 대개 드러나고, 3배는 같은 자리를 더 크게 벌린다. */
|
|
34
|
-
const FACTOR = 2;
|
|
35
|
-
const AXES = ['x', 'y', 'z'];
|
|
36
|
-
/** 이 배율에서 부품들이 차지하는 구간. */
|
|
37
|
-
function spansAt(members, base, scale) {
|
|
38
|
-
return members.map(member => {
|
|
39
|
-
/*
|
|
40
|
-
**배율을 한 번만 준다.** 축마다 따로 주면 `aspect-` 처럼 다른 축을 보는 규칙이 자기 축만 늘어난
|
|
41
|
-
세상을 보게 되어, 실제로 그려지는 것과 다른 답이 나온다.
|
|
42
|
-
*/
|
|
43
|
-
const at = sizingPosition(member, scale, base);
|
|
44
|
-
const sized = sizingScale(member, scale, base);
|
|
45
|
-
const extent = rotatedExtentOf(member);
|
|
46
|
-
const box = {};
|
|
47
|
-
for (const axis of AXES) {
|
|
48
|
-
const centre = at[axis] * scale[axis];
|
|
49
|
-
const half = (extent[axis] * sized[axis] * scale[axis]) / 2;
|
|
50
|
-
box[axis] = [centre - half, centre + half];
|
|
51
|
-
}
|
|
52
|
-
return { name: member.name, box };
|
|
53
|
-
});
|
|
54
|
-
}
|
|
55
|
-
function meets(a, b) {
|
|
56
|
-
return AXES.every(axis => a.box[axis][0] - SKIN <= b.box[axis][1] && b.box[axis][0] - SKIN <= a.box[axis][1]);
|
|
57
|
-
}
|
|
58
|
-
/** 닿는 것끼리 이어 덩어리를 만든다. 덩어리마다 부품 이름을 담는다. */
|
|
59
|
-
function clumpsOf(spans) {
|
|
60
|
-
const owner = spans.map((_, at) => at);
|
|
61
|
-
const rootOf = (at) => (owner[at] === at ? at : (owner[at] = rootOf(owner[at])));
|
|
62
|
-
for (let i = 0; i < spans.length; i++) {
|
|
63
|
-
for (let j = i + 1; j < spans.length; j++) {
|
|
64
|
-
if (meets(spans[i], spans[j]))
|
|
65
|
-
owner[rootOf(i)] = rootOf(j);
|
|
66
|
-
}
|
|
67
|
-
}
|
|
68
|
-
const by = new Map();
|
|
69
|
-
spans.forEach((span, at) => {
|
|
70
|
-
const key = rootOf(at);
|
|
71
|
-
if (!by.has(key))
|
|
72
|
-
by.set(key, []);
|
|
73
|
-
by.get(key).push(span.name);
|
|
74
|
-
});
|
|
75
|
-
return [...by.values()];
|
|
76
|
-
}
|
|
77
|
-
/** 사람이 눈으로 보는 것 — 갈라짐은 언제나 이것이다. */
|
|
78
|
-
const WHY_SPLIT = '배치할 때 크기를 바꾸면 이 부품이 맞댄 면에서 떨어져 공중에 뜬 것처럼 보인다. 사람 눈에는 부서진 것이다';
|
|
79
|
-
/**
|
|
80
|
-
* 자리가 떨어지면 보이는 것은 **부품이 아니라 물건**이다.
|
|
81
|
-
*
|
|
82
|
-
* 자리는 그려지지 않으므로 화면에서 갈라진 자리 자체는 아무도 못 본다. 사람이 보는 것은 그
|
|
83
|
-
* 자리에 놓인 재고가 선반을 벗어나 허공에 뜬 모습이고, 그것을 「부품이 떨어진다」고 말하면
|
|
84
|
-
* 저작자는 어느 부품을 봐야 할지 찾지 못한다.
|
|
85
|
-
*/
|
|
86
|
-
const WHY_SPLIT_SLOT = '배치할 때 크기를 바꾸면 물건을 놓는 자리가 그 면에서 떨어진다. 자리에 놓인 재고가 표면을 벗어나 공중에 뜬 것처럼 보인다';
|
|
87
|
-
/**
|
|
88
|
-
* 떨어져 나온 쪽에 자리가 있나.
|
|
89
|
-
*
|
|
90
|
-
* 자리가 **몸통에 붙어 있는데** 다른 부품이 떨어진 경우까지 자리 이야기를 하면, 저작자는 멀쩡한
|
|
91
|
-
* 자리를 들여다보게 된다. 가장 큰 덩어리를 몸통으로 보고, 그 밖에 있는 자리만 센다.
|
|
92
|
-
*/
|
|
93
|
-
function slotCameOff(clumps, isSlot) {
|
|
94
|
-
if (clumps.length < 2 || isSlot.size === 0)
|
|
95
|
-
return false;
|
|
96
|
-
const body = clumps.reduce((big, clump) => (clump.length > big.length ? clump : big));
|
|
97
|
-
return clumps.some(clump => clump !== body && clump.some(name => isSlot.has(name)));
|
|
98
|
-
}
|
|
99
|
-
/** 어느 면에 붙어 있나 — 상자 가운데를 기준으로 그 부품이 놓인 쪽. */
|
|
100
|
-
function sideOf(member, axis) {
|
|
101
|
-
return member.transform.position[axis] >= 0 ? 'max' : 'min';
|
|
102
|
-
}
|
|
103
|
-
/**
|
|
104
|
-
* **무엇을 바꾸면 붙어 있나.**
|
|
105
|
-
*
|
|
106
|
-
* 갈라진 두 덩어리를 축마다 견줘 원인을 하나 고른다. 두 가지가 실제로 나온다.
|
|
107
|
-
*
|
|
108
|
-
* 붙잡는 면이 다르다 한쪽은 바닥에서 잰 거리를, 다른 쪽은 천장에서 잰 거리를 지킨다.
|
|
109
|
-
* 시그널타워가 3배에서 램프를 공중에 띄운 그 모양이다
|
|
110
|
-
* 자리만 비례로 간다 맞댄 쪽은 단면을 지키느라(`keepRound`) 덜 커지는데, 이 부품의 자리는
|
|
111
|
-
* 상자와 함께 온전히 커져 표면을 지나쳐 버린다
|
|
112
|
-
*
|
|
113
|
-
* 둘 다 아니면 규칙 이름을 대지 않고 **무엇을 재 보라고**만 말한다 — 원인을 지어내지 않는다.
|
|
114
|
-
*/
|
|
115
|
-
function remedyFor(members, base, axes, clumps, scale) {
|
|
116
|
-
/*
|
|
117
|
-
**어느 쪽이 떨어져 나온 것인지는 크기로 정하지 않는다.**
|
|
118
|
-
|
|
119
|
-
처음에는 「부품 수가 적은 덩어리가 떨어져 나온 쪽」으로 두었다. 둘 다 한 개일 때 그 기준이
|
|
120
|
-
아무것도 정하지 못했고(시험이 그것을 잡았다), 원인이 있는데도 「같은 규칙을 따르는지 본다」로
|
|
121
|
-
떨어졌다. 그래서 **양쪽으로 다 따져 보고 설명이 되는 쪽**을 고른다. 고칠 부품이 적은 쪽을
|
|
122
|
-
먼저 시도하므로, 둘 다 설명되면 적은 수정을 권한다.
|
|
123
|
-
*/
|
|
124
|
-
const candidates = clumps
|
|
125
|
-
.map((clump, at) => ({
|
|
126
|
-
broken: members.filter(member => clump.includes(member.name)),
|
|
127
|
-
main: members.filter(member => clumps.some((other, i) => i !== at && other.includes(member.name)))
|
|
128
|
-
}))
|
|
129
|
-
.filter(pair => pair.broken.length > 0 && pair.main.length > 0)
|
|
130
|
-
.sort((a, b) => a.broken.length - b.broken.length);
|
|
131
|
-
for (const { broken, main } of candidates) {
|
|
132
|
-
const named = broken.map(member => member.name).join('·');
|
|
133
|
-
/*
|
|
134
|
-
① 붙잡는 면이 다르다 — 한쪽은 바닥에서, 다른 쪽은 천장에서 잰 거리를 지킨다.
|
|
135
|
-
|
|
136
|
-
**어느 쪽을 고쳐야 하는지는 말하지 않는다.** 게이트는 저작자의 뜻을 모른다 — 받침을 바닥에
|
|
137
|
-
붙여 둔 것이 맞을 수도 있고, 램프를 천장에 매단 것이 맞을 수도 있다. 한쪽을 지목했더니
|
|
138
|
-
「받침을 max 로 맞추라」는 틀린 조언이 나왔다(시험이 그것을 잡았다).
|
|
139
|
-
|
|
140
|
-
그래서 양쪽을 이름과 값으로 말하고, 흔한 경우의 눈대중만 덧붙인다.
|
|
141
|
-
*/
|
|
142
|
-
for (const axis of axes) {
|
|
143
|
-
const brokenAnchors = new Set(broken.map(member => anchorOf(member, base, axis)));
|
|
144
|
-
const mainAnchors = new Set(main.map(member => anchorOf(member, base, axis)));
|
|
145
|
-
const mixed = [...brokenAnchors].filter(rule => !mainAnchors.has(rule));
|
|
146
|
-
if (mixed.length && mainAnchors.size === 1) {
|
|
147
|
-
const [theirs] = [...mainAnchors];
|
|
148
|
-
const others = main.map(member => member.name).join('·');
|
|
149
|
-
return (`${named} 의 anchor.${axis} 는 ${mixed.join('·')} 이고 ${others} 는 ${theirs} 다 — ` +
|
|
150
|
-
`한 축에서 서로 다른 면을 붙잡으면 늘어날 때 벌어진다. 둘을 같은 값으로 맞춘다` +
|
|
151
|
-
(axis === 'y' ? ' (바닥에 서는 것이면 min 이다)' : ''));
|
|
152
|
-
}
|
|
153
|
-
}
|
|
154
|
-
/*
|
|
155
|
-
② 붙잡는 면이 같은데도 갈라진다 — 맞댄 쪽의 **크기**가 상자만큼 못 커지는 경우다(단면 유지).
|
|
156
|
-
그 값을 그대로 보여 준다. 「덜 커진다」는 말보다 1.41배와 2배를 나란히 두는 것이 빠르다.
|
|
157
|
-
*/
|
|
158
|
-
for (const axis of axes) {
|
|
159
|
-
const grow = scale[axis];
|
|
160
|
-
const slowest = main
|
|
161
|
-
.map(member => ({ member, net: sizingScale(member, scale, base)[axis] * grow }))
|
|
162
|
-
.sort((a, b) => a.net - b.net)[0];
|
|
163
|
-
if (slowest && slowest.net < grow - 0.01) {
|
|
164
|
-
const face = sideOf(broken[0], axis);
|
|
165
|
-
return (
|
|
166
|
-
/* 「쪽은」으로 받는다 — 부품 이름은 영문 식별자라 은/는 을 고를 수 없다. */
|
|
167
|
-
`맞댄 ${slowest.member.name} 쪽은 단면을 지키느라 ${axis} 로 ${slowest.net.toFixed(2)}배만 커지는데 ` +
|
|
168
|
-
`${named} 의 자리는 ${grow}배로 간다. ${named} 의 anchor.${axis} 를 ${face} 로 두면 그 면에서 잰 거리를 지켜 붙어 있는다`);
|
|
169
|
-
}
|
|
170
|
-
}
|
|
171
|
-
}
|
|
172
|
-
/* 둘 다 아니면 규칙 이름을 대지 않는다 — 원인을 지어내지 않고 무엇을 재 보라고만 말한다. */
|
|
173
|
-
const all = clumps.map(clump => [...clump].sort().join('+')).join(' | ');
|
|
174
|
-
return `${all} 쪽이 ${axes.join('·')} 에서 같은 규칙을 따르는지 본다`;
|
|
175
|
-
}
|
|
176
|
-
/**
|
|
177
|
-
* 크기를 바꿔 봐도 한 덩어리인가.
|
|
178
|
-
*
|
|
179
|
-
* 1배에서 이미 갈라져 있으면 그것을 먼저 말하고(`sizing-loose`), 그 뒤 일곱 조합에서 **덩어리가
|
|
180
|
-
* 늘어나는** 경우를 찾는다. 늘어나지 않으면 조용하다 — 부품이 움직였는지가 아니라 **떨어졌는지**를
|
|
181
|
-
* 보기 때문이다.
|
|
182
|
-
*/
|
|
183
|
-
export function sizingReport(blueprint, factor = FACTOR) {
|
|
184
|
-
const drawn = blueprint.groups.flatMap((group) => group.members);
|
|
185
|
-
const findings = [];
|
|
186
|
-
if (!drawn.length) {
|
|
187
|
-
return { findings, clumpsAtOne: 0, factor };
|
|
188
|
-
}
|
|
189
|
-
/*
|
|
190
|
-
**자리도 함께 세운다. 문은 아니다.**
|
|
191
|
-
|
|
192
|
-
자리(slot)는 안에 있다 — 물건이 앉을 면 위다. 그 면이 커질 때 자리가 따라가지 않으면 재고가
|
|
193
|
-
허공에 뜬다. 그리는 부품이 떨어지는 것과 같은 결함이고, 자리는 그려지지 않으니 **저작자가
|
|
194
|
-
화면을 봐서는 영영 모른다.** 게이트가 아니면 잡을 자리가 없다.
|
|
195
|
-
|
|
196
|
-
문(port)은 밖이다. 몸에서 떨어진 자리에 두는 것이 정상이라, 함께 세면 문 하나 있는 도형마다
|
|
197
|
-
「1배에서 이미 두 조각」이 뜬다. 옳은 저작을 결함이라 부르는 검사는 곧 아무도 안 읽는다.
|
|
198
|
-
*/
|
|
199
|
-
const slots = (blueprint.anchors ?? []).filter(at => at.roles.includes('slot'));
|
|
200
|
-
const members = [...drawn, ...slots];
|
|
201
|
-
const isSlot = new Set(slots.map(at => at.name));
|
|
202
|
-
const one = clumpsOf(spansAt(members, blueprint.base, { x: 1, y: 1, z: 1 }));
|
|
203
|
-
if (one.length > 1) {
|
|
204
|
-
findings.push({
|
|
205
|
-
code: 'sizing-loose',
|
|
206
|
-
message: `1배에서 이미 ${one.length} 조각이다. 크기를 바꾸기 전에 이미 떨어져 있다`,
|
|
207
|
-
why: slotCameOff(one, isSlot)
|
|
208
|
-
? '물건이 앉는 자리가 놓일 면에서 이미 떨어져 있다. 1배에서도 재고가 떠 보이고, 크기를 바꾸면 그 틈이 함께 커진다'
|
|
209
|
-
: '붙어 있어야 할 부품들이 저작 자체에서 떨어져 있다. 크기를 바꾸면 그 틈이 함께 커진다',
|
|
210
|
-
how: `${one.map(clump => [...clump].sort().join('+')).join(' · ')} 가 서로 닿도록 자리나 크기를 맞춘다. 일부러 띄운 것이면 그대로 두어도 발행은 된다`,
|
|
211
|
-
clumps: one
|
|
212
|
-
});
|
|
213
|
-
}
|
|
214
|
-
for (const way of SIZING_WAYS) {
|
|
215
|
-
const scale = { x: 1, y: 1, z: 1 };
|
|
216
|
-
for (const axis of way.axes)
|
|
217
|
-
scale[axis] = factor;
|
|
218
|
-
const grown = clumpsOf(spansAt(members, blueprint.base, scale));
|
|
219
|
-
if (grown.length > one.length) {
|
|
220
|
-
findings.push({
|
|
221
|
-
code: 'sizing-splits',
|
|
222
|
-
way: way.name,
|
|
223
|
-
message: `${way.name} 축을 ${factor}배로 하면 ${one.length} 조각이 ${grown.length} 조각으로 갈라진다`,
|
|
224
|
-
/* 떨어져 나온 쪽이 자리이면 사람이 보는 것은 부품이 아니라 그 위의 물건이다. */
|
|
225
|
-
why: slotCameOff(grown, isSlot) ? WHY_SPLIT_SLOT : WHY_SPLIT,
|
|
226
|
-
how: remedyFor(members, blueprint.base, way.axes, grown, scale),
|
|
227
|
-
clumps: grown
|
|
228
|
-
});
|
|
229
|
-
}
|
|
230
|
-
}
|
|
231
|
-
return { findings, clumpsAtOne: one.length, factor };
|
|
232
|
-
}
|
|
233
|
-
/** 정본 문자열이 아니라 객체를 받는 쪽. 부르는 자리가 이미 컴파일해 두었으면 위 함수를 쓴다. */
|
|
234
|
-
export function sizingReportOf(source, factor = FACTOR) {
|
|
235
|
-
return sizingReport(compile(source), factor);
|
|
236
|
-
}
|
|
237
|
-
/**
|
|
238
|
-
* Measured, reversible anchor alternatives for a sizing split.
|
|
239
|
-
*
|
|
240
|
-
* The gate never infers author intent from prose. Instead it tries a small set of explicit anchor
|
|
241
|
-
* changes on the parts named by the measured clumps, keeps only alternatives that reduce blocking
|
|
242
|
-
* splits without creating more, and leaves final selection to the author.
|
|
243
|
-
*/
|
|
244
|
-
export function sizingFixCandidatesOf(source, factor = FACTOR) {
|
|
245
|
-
const baseline = sizingReportOf(source, factor);
|
|
246
|
-
const blocked = baseline.findings.filter(finding => finding.code === 'sizing-splits');
|
|
247
|
-
const baselineCount = blocked.length;
|
|
248
|
-
const seen = new Set();
|
|
249
|
-
const candidates = [];
|
|
250
|
-
for (const finding of blocked) {
|
|
251
|
-
if (!finding.way)
|
|
252
|
-
continue;
|
|
253
|
-
const axes = finding.way.split('-').filter((axis) => AXES.includes(axis));
|
|
254
|
-
const names = new Set(finding.clumps.flat());
|
|
255
|
-
for (const part of source.parts) {
|
|
256
|
-
if (!names.has(part.name))
|
|
257
|
-
continue;
|
|
258
|
-
for (const axis of axes) {
|
|
259
|
-
for (const to of ['min', 'center', 'max', 'span']) {
|
|
260
|
-
if (part.anchor?.[axis] === to)
|
|
261
|
-
continue;
|
|
262
|
-
const next = {
|
|
263
|
-
...source,
|
|
264
|
-
parts: source.parts.map(one => one.name !== part.name
|
|
265
|
-
? one
|
|
266
|
-
: { ...one, anchor: { ...(one.anchor ?? {}), [axis]: to } })
|
|
267
|
-
};
|
|
268
|
-
const after = sizingReportOf(next, factor);
|
|
269
|
-
const afterBlocked = after.findings.filter(one => one.code === 'sizing-splits');
|
|
270
|
-
const resolved = baselineCount - afterBlocked.length;
|
|
271
|
-
if (resolved <= 0)
|
|
272
|
-
continue;
|
|
273
|
-
const key = `${part.name}:${axis}:${to}`;
|
|
274
|
-
if (seen.has(key))
|
|
275
|
-
continue;
|
|
276
|
-
seen.add(key);
|
|
277
|
-
candidates.push({ findingWay: finding.way, part: part.name, axis, from: part.anchor?.[axis], to, resolved });
|
|
278
|
-
}
|
|
279
|
-
}
|
|
280
|
-
}
|
|
281
|
-
}
|
|
282
|
-
return candidates.sort((a, b) => b.resolved - a.resolved || a.part.localeCompare(b.part)).slice(0, 12);
|
|
283
|
-
}
|
|
284
|
-
//# sourceMappingURL=gate.js.map
|
package/dist/gate.js.map
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"gate.js","sourceRoot":"","sources":["../src/gate.ts"],"names":[],"mappings":"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"}
|
package/dist/grouping.d.ts
DELETED
|
@@ -1,121 +0,0 @@
|
|
|
1
|
-
import type { AnimationChannel, FigurePart, Vec3 } from './types.ts';
|
|
2
|
-
/**
|
|
3
|
-
* The parts any clip moves.
|
|
4
|
-
*
|
|
5
|
-
* Merging is decided per part, and a clip names its parts from the outside, so
|
|
6
|
-
* the two have to be brought together before grouping can answer anything.
|
|
7
|
-
*
|
|
8
|
-
* It takes anything with channels, not an `AnimationClip`, because a parameter's clip is the
|
|
9
|
-
* same shape without the name — and what decides merging is being transformed on its own, not
|
|
10
|
-
* what does the transforming (ADR-0051 decision ③).
|
|
11
|
-
*/
|
|
12
|
-
export declare function animatedNames(clips: readonly {
|
|
13
|
-
channels?: AnimationChannel[];
|
|
14
|
-
}[] | undefined): ReadonlySet<string>;
|
|
15
|
-
/**
|
|
16
|
-
* The parts a source moves, by a clip or by a parameter.
|
|
17
|
-
*
|
|
18
|
-
* compile and the release gate both need this set, and they must read it the same way: the gate
|
|
19
|
-
* once read `animations` only, so a figure driven by parameters showed fewer moving parts and
|
|
20
|
-
* fewer draw calls to the gate than compile produced (FORKLIFT: 13 moving parts and 18 draw calls
|
|
21
|
-
* in the blueprint, 0 and 10 at the gate).
|
|
22
|
-
*/
|
|
23
|
-
export declare function movingNames(source: {
|
|
24
|
-
animations?: readonly {
|
|
25
|
-
channels?: AnimationChannel[];
|
|
26
|
-
}[];
|
|
27
|
-
parameters?: readonly {
|
|
28
|
-
clip?: {
|
|
29
|
-
channels?: AnimationChannel[];
|
|
30
|
-
};
|
|
31
|
-
}[];
|
|
32
|
-
}): ReadonlySet<string>;
|
|
33
|
-
/**
|
|
34
|
-
* Which joint's frame each part moves in: the nearest joint on its parent chain, the part itself included.
|
|
35
|
-
*
|
|
36
|
-
* A part missing from the map hangs from the figure frame. Parts in different frames cannot merge, since
|
|
37
|
-
* one merged geometry takes one transform (ADR-0066 decision 4).
|
|
38
|
-
*
|
|
39
|
-
* The walk stops at a name it has already seen, so a cycle (which validate reports) does not loop.
|
|
40
|
-
*/
|
|
41
|
-
export declare function jointFrames(source: {
|
|
42
|
-
parts: readonly {
|
|
43
|
-
name: string;
|
|
44
|
-
parent?: string;
|
|
45
|
-
}[];
|
|
46
|
-
joints?: readonly {
|
|
47
|
-
name: string;
|
|
48
|
-
child: string;
|
|
49
|
-
}[];
|
|
50
|
-
}): ReadonlyMap<string, string>;
|
|
51
|
-
/**
|
|
52
|
-
* A part draws on its own when it cannot be merged with its neighbours.
|
|
53
|
-
*
|
|
54
|
-
* A curved part stands alone whatever its sizing. A merged geometry takes one
|
|
55
|
-
* transform, and an instance scaled differently on each axis turns a cylinder
|
|
56
|
-
* merged into it into an elliptical one -- declared round, drawn oval. Keeping
|
|
57
|
-
* it round means keeping its own transform.
|
|
58
|
-
*
|
|
59
|
-
* `needsOwnMesh` in things-scene must answer the same. When the two disagree,
|
|
60
|
-
* the number the report shows and the number the screen draws come apart, which
|
|
61
|
-
* is the fault this whole file was written to close.
|
|
62
|
-
*/
|
|
63
|
-
export declare function standsAlone(part: FigurePart, animated?: ReadonlySet<string>): boolean;
|
|
64
|
-
/**
|
|
65
|
-
* What a part merges by: its material and slot, within one joint frame. compile and the gate share it so
|
|
66
|
-
* the groups compile builds and the draw calls the gate counts stay the same number.
|
|
67
|
-
*/
|
|
68
|
-
export declare function mergeKeyOf(part: FigurePart, frames?: ReadonlyMap<string, string>): string;
|
|
69
|
-
/**
|
|
70
|
-
* Does this part get drawn?
|
|
71
|
-
*
|
|
72
|
-
* A part carrying a `capability` spec is a **place** -- a slot something sits
|
|
73
|
-
* in, a port something enters by. It has no material and no geometry, and
|
|
74
|
-
* `compile` routes it to `anchors` rather than to a group.
|
|
75
|
-
*
|
|
76
|
-
* Every count of what drawing costs has to skip it. Left in, it does not merely
|
|
77
|
-
* inflate a number: `groupKeyOf` reads a material that is not there and throws
|
|
78
|
-
* on a source the format calls valid.
|
|
79
|
-
*/
|
|
80
|
-
export declare function isDrawn(part: FigurePart): boolean;
|
|
81
|
-
/**
|
|
82
|
-
* The merge groups a set of parts produces.
|
|
83
|
-
*
|
|
84
|
-
* Each entry is the parts that end up in one merged geometry. Parts that stand
|
|
85
|
-
* alone get an entry of their own. Parts that are not drawn make no entry.
|
|
86
|
-
*/
|
|
87
|
-
export declare function groupsOf(parts: readonly FigurePart[], animated?: ReadonlySet<string>, frames?: ReadonlyMap<string, string>): FigurePart[][];
|
|
88
|
-
/**
|
|
89
|
-
* Does this part hold its section circular under a lopsided instance?
|
|
90
|
-
*
|
|
91
|
-
* Only curved primitives can, and they do unless the author turns it off. A
|
|
92
|
-
* bolt head nobody looks at is worth merging; a wheel is not.
|
|
93
|
-
*/
|
|
94
|
-
export declare function keepsRound(part: FigurePart): boolean;
|
|
95
|
-
/**
|
|
96
|
-
* How many meshes one repeat part draws **as authored**.
|
|
97
|
-
*
|
|
98
|
-
* The count grows with the instance, since the row fills the box it is given.
|
|
99
|
-
* This is the count at scale 1 -- the asset's own size, which is what the
|
|
100
|
-
* author is looking at and the only number that does not depend on where it
|
|
101
|
-
* ends up.
|
|
102
|
-
*
|
|
103
|
-
* Must match `repeatPlan` in things-scene. If they drift, the screen and the
|
|
104
|
-
* report disagree about the same tray.
|
|
105
|
-
*/
|
|
106
|
-
export declare function repeatCountOf(part: FigurePart, base: Vec3): number;
|
|
107
|
-
/**
|
|
108
|
-
* Draw calls one instance costs. **This is what the limit is about.**
|
|
109
|
-
*
|
|
110
|
-
* A merged group is one call. A repeat part is one call per copy.
|
|
111
|
-
*/
|
|
112
|
-
export declare function drawCallsOf(parts: readonly FigurePart[], base: Vec3, animated?: ReadonlySet<string>, frames?: ReadonlyMap<string, string>): number;
|
|
113
|
-
/**
|
|
114
|
-
* Draw calls for one merged group.
|
|
115
|
-
*
|
|
116
|
-
* **A merged group is one call however many parts went into it** -- that is
|
|
117
|
-
* what merging is for. Only repeat multiplies, and a repeat part always stands
|
|
118
|
-
* alone, so a group either holds one repeat part or is a single call.
|
|
119
|
-
*/
|
|
120
|
-
export declare function callsForGroup(group: readonly FigurePart[], base: Vec3): number;
|
|
121
|
-
//# sourceMappingURL=grouping.d.ts.map
|
package/dist/grouping.d.ts.map
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"grouping.d.ts","sourceRoot":"","sources":["../src/grouping.ts"],"names":[],"mappings":"AAmCA,OAAO,KAAK,EAAE,gBAAgB,EAAE,UAAU,EAAE,IAAI,EAAE,MAAM,YAAY,CAAA;AAEpE;;;;;;;;;GASG;AACH,wBAAgB,aAAa,CAAC,KAAK,EAAE,SAAS;IAAE,QAAQ,CAAC,EAAE,gBAAgB,EAAE,CAAA;CAAE,EAAE,GAAG,SAAS,GAAG,WAAW,CAAC,MAAM,CAAC,CAQlH;AAED;;;;;;;GAOG;AACH,wBAAgB,WAAW,CAAC,MAAM,EAAE;IAClC,UAAU,CAAC,EAAE,SAAS;QAAE,QAAQ,CAAC,EAAE,gBAAgB,EAAE,CAAA;KAAE,EAAE,CAAA;IACzD,UAAU,CAAC,EAAE,SAAS;QAAE,IAAI,CAAC,EAAE;YAAE,QAAQ,CAAC,EAAE,gBAAgB,EAAE,CAAA;SAAE,CAAA;KAAE,EAAE,CAAA;CACrE,GAAG,WAAW,CAAC,MAAM,CAAC,CAKtB;AAED;;;;;;;GAOG;AACH,wBAAgB,WAAW,CAAC,MAAM,EAAE;IAClC,KAAK,EAAE,SAAS;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,MAAM,CAAC,EAAE,MAAM,CAAA;KAAE,EAAE,CAAA;IACnD,MAAM,CAAC,EAAE,SAAS;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,KAAK,EAAE,MAAM,CAAA;KAAE,EAAE,CAAA;CACpD,GAAG,WAAW,CAAC,MAAM,EAAE,MAAM,CAAC,CAqB9B;AAED;;;;;;;;;;;GAWG;AACH,wBAAgB,WAAW,CAAC,IAAI,EAAE,UAAU,EAAE,QAAQ,GAAE,WAAW,CAAC,MAAM,CAAS,GAAG,OAAO,CAI5F;AAKD;;;GAGG;AACH,wBAAgB,UAAU,CAAC,IAAI,EAAE,UAAU,EAAE,MAAM,GAAE,WAAW,CAAC,MAAM,EAAE,MAAM,CAAa,GAAG,MAAM,CAGpG;AAED;;;;;;;;;;GAUG;AACH,wBAAgB,OAAO,CAAC,IAAI,EAAE,UAAU,GAAG,OAAO,CAEjD;AAED;;;;;GAKG;AACH,wBAAgB,QAAQ,CACtB,KAAK,EAAE,SAAS,UAAU,EAAE,EAC5B,QAAQ,GAAE,WAAW,CAAC,MAAM,CAAS,EACrC,MAAM,GAAE,WAAW,CAAC,MAAM,EAAE,MAAM,CAAa,GAC9C,UAAU,EAAE,EAAE,CA0BhB;AAED;;;;;GAKG;AACH,wBAAgB,UAAU,CAAC,IAAI,EAAE,UAAU,GAAG,OAAO,CAGpD;AAED;;;;;;;;;;GAUG;AACH,wBAAgB,aAAa,CAAC,IAAI,EAAE,UAAU,EAAE,IAAI,EAAE,IAAI,GAAG,MAAM,CASlE;AAED;;;;GAIG;AACH,wBAAgB,WAAW,CACzB,KAAK,EAAE,SAAS,UAAU,EAAE,EAC5B,IAAI,EAAE,IAAI,EACV,QAAQ,GAAE,WAAW,CAAC,MAAM,CAAS,EACrC,MAAM,GAAE,WAAW,CAAC,MAAM,EAAE,MAAM,CAAa,GAC9C,MAAM,CAER;AAED;;;;;;GAMG;AACH,wBAAgB,aAAa,CAAC,KAAK,EAAE,SAAS,UAAU,EAAE,EAAE,IAAI,EAAE,IAAI,GAAG,MAAM,CAI9E"}
|
package/dist/grouping.js
DELETED
|
@@ -1,224 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* How parts turn into draw calls. **One answer, used by compile and by the
|
|
3
|
-
* policy check.**
|
|
4
|
-
*
|
|
5
|
-
* ## Why this file exists
|
|
6
|
-
*
|
|
7
|
-
* The policy counted `groupKeyOf` -- distinct colour and slot combinations --
|
|
8
|
-
* while `compile` split further and the runtime split further still. Three
|
|
9
|
-
* places had three answers, and the one shown to the author was the smallest.
|
|
10
|
-
*
|
|
11
|
-
* conveyor policy said 3 compile made 17 the screen drew 17
|
|
12
|
-
* cell tray policy said 2 compile made 2 the screen drew 9
|
|
13
|
-
*
|
|
14
|
-
* A cell tray that draws nine times passed a limit of three with room to
|
|
15
|
-
* spare. Raising the limit would not have touched that -- the number being
|
|
16
|
-
* compared was the wrong one.
|
|
17
|
-
*
|
|
18
|
-
* ## The three splits
|
|
19
|
-
*
|
|
20
|
-
* animation a part some clip moves goes on its own, since it cannot share a
|
|
21
|
-
* merged geometry with parts that stay put
|
|
22
|
-
* sizing a part that does not scale with the instance takes its own
|
|
23
|
-
* transform, and a merged geometry only takes one
|
|
24
|
-
* curvature a cylinder or sphere takes its own transform too, or the one
|
|
25
|
-
* transform a merged geometry gets turns it oval
|
|
26
|
-
* repeat one authored part, many meshes -- each copy is a draw call
|
|
27
|
-
*
|
|
28
|
-
* The first two make groups. The third multiplies inside a group, which is why
|
|
29
|
-
* `drawCallsOf` is not simply `groupsOf().length`.
|
|
30
|
-
*
|
|
31
|
-
* Before any of that, a part that is not drawn at all -- a capability anchor --
|
|
32
|
-
* drops out. See `isDrawn`.
|
|
33
|
-
*/
|
|
34
|
-
import { groupKeyOf } from "./keys.js";
|
|
35
|
-
import { CURVED_PRIMITIVES, DEFAULT_SIZING, REPEAT_LIMIT } from "./types.js";
|
|
36
|
-
/**
|
|
37
|
-
* The parts any clip moves.
|
|
38
|
-
*
|
|
39
|
-
* Merging is decided per part, and a clip names its parts from the outside, so
|
|
40
|
-
* the two have to be brought together before grouping can answer anything.
|
|
41
|
-
*
|
|
42
|
-
* It takes anything with channels, not an `AnimationClip`, because a parameter's clip is the
|
|
43
|
-
* same shape without the name — and what decides merging is being transformed on its own, not
|
|
44
|
-
* what does the transforming (ADR-0051 decision ③).
|
|
45
|
-
*/
|
|
46
|
-
export function animatedNames(clips) {
|
|
47
|
-
const names = new Set();
|
|
48
|
-
for (const clip of clips ?? []) {
|
|
49
|
-
for (const channel of clip.channels ?? []) {
|
|
50
|
-
if (typeof channel?.target === 'string')
|
|
51
|
-
names.add(channel.target);
|
|
52
|
-
}
|
|
53
|
-
}
|
|
54
|
-
return names;
|
|
55
|
-
}
|
|
56
|
-
/**
|
|
57
|
-
* The parts a source moves, by a clip or by a parameter.
|
|
58
|
-
*
|
|
59
|
-
* compile and the release gate both need this set, and they must read it the same way: the gate
|
|
60
|
-
* once read `animations` only, so a figure driven by parameters showed fewer moving parts and
|
|
61
|
-
* fewer draw calls to the gate than compile produced (FORKLIFT: 13 moving parts and 18 draw calls
|
|
62
|
-
* in the blueprint, 0 and 10 at the gate).
|
|
63
|
-
*/
|
|
64
|
-
export function movingNames(source) {
|
|
65
|
-
return new Set([
|
|
66
|
-
...animatedNames(source.animations),
|
|
67
|
-
...animatedNames((source.parameters ?? []).map(parameter => parameter.clip ?? {}))
|
|
68
|
-
]);
|
|
69
|
-
}
|
|
70
|
-
/**
|
|
71
|
-
* Which joint's frame each part moves in: the nearest joint on its parent chain, the part itself included.
|
|
72
|
-
*
|
|
73
|
-
* A part missing from the map hangs from the figure frame. Parts in different frames cannot merge, since
|
|
74
|
-
* one merged geometry takes one transform (ADR-0066 decision 4).
|
|
75
|
-
*
|
|
76
|
-
* The walk stops at a name it has already seen, so a cycle (which validate reports) does not loop.
|
|
77
|
-
*/
|
|
78
|
-
export function jointFrames(source) {
|
|
79
|
-
const parentOf = new Map();
|
|
80
|
-
for (const part of source.parts)
|
|
81
|
-
if (typeof part.parent === 'string')
|
|
82
|
-
parentOf.set(part.name, part.parent);
|
|
83
|
-
const jointOfChild = new Map();
|
|
84
|
-
for (const joint of source.joints ?? [])
|
|
85
|
-
if (!jointOfChild.has(joint.child))
|
|
86
|
-
jointOfChild.set(joint.child, joint.name);
|
|
87
|
-
const frames = new Map();
|
|
88
|
-
for (const part of source.parts) {
|
|
89
|
-
const seen = new Set();
|
|
90
|
-
let at = part.name;
|
|
91
|
-
while (at !== undefined && !seen.has(at)) {
|
|
92
|
-
seen.add(at);
|
|
93
|
-
const joint = jointOfChild.get(at);
|
|
94
|
-
if (joint !== undefined) {
|
|
95
|
-
frames.set(part.name, joint);
|
|
96
|
-
break;
|
|
97
|
-
}
|
|
98
|
-
at = parentOf.get(at);
|
|
99
|
-
}
|
|
100
|
-
}
|
|
101
|
-
return frames;
|
|
102
|
-
}
|
|
103
|
-
/**
|
|
104
|
-
* A part draws on its own when it cannot be merged with its neighbours.
|
|
105
|
-
*
|
|
106
|
-
* A curved part stands alone whatever its sizing. A merged geometry takes one
|
|
107
|
-
* transform, and an instance scaled differently on each axis turns a cylinder
|
|
108
|
-
* merged into it into an elliptical one -- declared round, drawn oval. Keeping
|
|
109
|
-
* it round means keeping its own transform.
|
|
110
|
-
*
|
|
111
|
-
* `needsOwnMesh` in things-scene must answer the same. When the two disagree,
|
|
112
|
-
* the number the report shows and the number the screen draws come apart, which
|
|
113
|
-
* is the fault this whole file was written to close.
|
|
114
|
-
*/
|
|
115
|
-
export function standsAlone(part, animated = EMPTY) {
|
|
116
|
-
if (animated.has(part.name))
|
|
117
|
-
return true;
|
|
118
|
-
if ((part.sizing ?? DEFAULT_SIZING) !== 'scale')
|
|
119
|
-
return true;
|
|
120
|
-
return keepsRound(part);
|
|
121
|
-
}
|
|
122
|
-
const EMPTY = new Set();
|
|
123
|
-
const NO_FRAMES = new Map();
|
|
124
|
-
/**
|
|
125
|
-
* What a part merges by: its material and slot, within one joint frame. compile and the gate share it so
|
|
126
|
-
* the groups compile builds and the draw calls the gate counts stay the same number.
|
|
127
|
-
*/
|
|
128
|
-
export function mergeKeyOf(part, frames = NO_FRAMES) {
|
|
129
|
-
const frame = frames.get(part.name);
|
|
130
|
-
return frame === undefined ? groupKeyOf(part) : `${groupKeyOf(part)}@${frame}`;
|
|
131
|
-
}
|
|
132
|
-
/**
|
|
133
|
-
* Does this part get drawn?
|
|
134
|
-
*
|
|
135
|
-
* A part carrying a `capability` spec is a **place** -- a slot something sits
|
|
136
|
-
* in, a port something enters by. It has no material and no geometry, and
|
|
137
|
-
* `compile` routes it to `anchors` rather than to a group.
|
|
138
|
-
*
|
|
139
|
-
* Every count of what drawing costs has to skip it. Left in, it does not merely
|
|
140
|
-
* inflate a number: `groupKeyOf` reads a material that is not there and throws
|
|
141
|
-
* on a source the format calls valid.
|
|
142
|
-
*/
|
|
143
|
-
export function isDrawn(part) {
|
|
144
|
-
return part.capability === undefined;
|
|
145
|
-
}
|
|
146
|
-
/**
|
|
147
|
-
* The merge groups a set of parts produces.
|
|
148
|
-
*
|
|
149
|
-
* Each entry is the parts that end up in one merged geometry. Parts that stand
|
|
150
|
-
* alone get an entry of their own. Parts that are not drawn make no entry.
|
|
151
|
-
*/
|
|
152
|
-
export function groupsOf(parts, animated = EMPTY, frames = NO_FRAMES) {
|
|
153
|
-
const groups = [];
|
|
154
|
-
const byKey = new Map();
|
|
155
|
-
for (const part of parts) {
|
|
156
|
-
if (!isDrawn(part))
|
|
157
|
-
continue;
|
|
158
|
-
if (standsAlone(part, animated)) {
|
|
159
|
-
groups.push([part]);
|
|
160
|
-
continue;
|
|
161
|
-
}
|
|
162
|
-
const key = mergeKeyOf(part, frames);
|
|
163
|
-
const merged = byKey.get(key);
|
|
164
|
-
if (merged) {
|
|
165
|
-
merged.push(part);
|
|
166
|
-
continue;
|
|
167
|
-
}
|
|
168
|
-
const started = [part];
|
|
169
|
-
byKey.set(key, started);
|
|
170
|
-
groups.push(started);
|
|
171
|
-
}
|
|
172
|
-
return groups;
|
|
173
|
-
}
|
|
174
|
-
/**
|
|
175
|
-
* Does this part hold its section circular under a lopsided instance?
|
|
176
|
-
*
|
|
177
|
-
* Only curved primitives can, and they do unless the author turns it off. A
|
|
178
|
-
* bolt head nobody looks at is worth merging; a wheel is not.
|
|
179
|
-
*/
|
|
180
|
-
export function keepsRound(part) {
|
|
181
|
-
if (!CURVED_PRIMITIVES.includes(part.primitive))
|
|
182
|
-
return false;
|
|
183
|
-
return part.keepRound !== false;
|
|
184
|
-
}
|
|
185
|
-
/**
|
|
186
|
-
* How many meshes one repeat part draws **as authored**.
|
|
187
|
-
*
|
|
188
|
-
* The count grows with the instance, since the row fills the box it is given.
|
|
189
|
-
* This is the count at scale 1 -- the asset's own size, which is what the
|
|
190
|
-
* author is looking at and the only number that does not depend on where it
|
|
191
|
-
* ends up.
|
|
192
|
-
*
|
|
193
|
-
* Must match `repeatPlan` in things-scene. If they drift, the screen and the
|
|
194
|
-
* report disagree about the same tray.
|
|
195
|
-
*/
|
|
196
|
-
export function repeatCountOf(part, base) {
|
|
197
|
-
if (part.sizing !== 'repeat' || !part.repeat)
|
|
198
|
-
return 1;
|
|
199
|
-
const { axis, pitch } = part.repeat;
|
|
200
|
-
if (!(Number.isFinite(pitch) && pitch > 0))
|
|
201
|
-
return 1;
|
|
202
|
-
const room = Number.isFinite(base[axis]) && base[axis] > 0 ? base[axis] : pitch;
|
|
203
|
-
return Math.max(1, Math.min(REPEAT_LIMIT, Math.floor(room / pitch)));
|
|
204
|
-
}
|
|
205
|
-
/**
|
|
206
|
-
* Draw calls one instance costs. **This is what the limit is about.**
|
|
207
|
-
*
|
|
208
|
-
* A merged group is one call. A repeat part is one call per copy.
|
|
209
|
-
*/
|
|
210
|
-
export function drawCallsOf(parts, base, animated = EMPTY, frames = NO_FRAMES) {
|
|
211
|
-
return groupsOf(parts, animated, frames).reduce((total, group) => total + callsForGroup(group, base), 0);
|
|
212
|
-
}
|
|
213
|
-
/**
|
|
214
|
-
* Draw calls for one merged group.
|
|
215
|
-
*
|
|
216
|
-
* **A merged group is one call however many parts went into it** -- that is
|
|
217
|
-
* what merging is for. Only repeat multiplies, and a repeat part always stands
|
|
218
|
-
* alone, so a group either holds one repeat part or is a single call.
|
|
219
|
-
*/
|
|
220
|
-
export function callsForGroup(group, base) {
|
|
221
|
-
const only = group.length === 1 ? group[0] : undefined;
|
|
222
|
-
return only ? repeatCountOf(only, base) : 1;
|
|
223
|
-
}
|
|
224
|
-
//# sourceMappingURL=grouping.js.map
|