@ai-gui/plugin-physics 0.17.0 → 0.18.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 +26 -0
- package/dist/index.cjs +37 -1
- package/dist/index.js +37 -1
- package/package.json +2 -2
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,31 @@
|
|
|
1
1
|
# @ai-gui/plugin-physics
|
|
2
2
|
|
|
3
|
+
## 0.18.0
|
|
4
|
+
|
|
5
|
+
### Patch Changes
|
|
6
|
+
|
|
7
|
+
- Updated dependencies [a22ba20]
|
|
8
|
+
- @ai-gui/core@0.18.0
|
|
9
|
+
|
|
10
|
+
## 0.17.1
|
|
11
|
+
|
|
12
|
+
### Patch Changes
|
|
13
|
+
|
|
14
|
+
- a06c692: **The view box now holds the angle marks, the labels and the hatching.**
|
|
15
|
+
|
|
16
|
+
It was measured from bodies, surfaces and vector tips only. Everything else a mechanics diagram draws
|
|
17
|
+
sits outside those: the `30°` at the foot of an incline is an arc 28 from its vertex with a label 14
|
|
18
|
+
further out and was measured by nothing at all, so on any diagram whose incline reaches the left edge it
|
|
19
|
+
was simply outside the picture — the one label a 斜面 diagram cannot do without. A vector's label is
|
|
20
|
+
written past its arrowhead and then runs the width of its own text, so "mg cos(30°)" hung off the frame
|
|
21
|
+
beside an arrow pointing at nothing. Hatching hangs below its surface by its own length.
|
|
22
|
+
|
|
23
|
+
Text is estimated rather than measured — this renders to a string, with no DOM to measure in — and errs
|
|
24
|
+
wide: CJK at a full em, Latin at half. A box slightly too big shows white space; one slightly too small
|
|
25
|
+
cuts a word in half. An explicit `view` is still left exactly as given.
|
|
26
|
+
|
|
27
|
+
- @ai-gui/core@0.17.1
|
|
28
|
+
|
|
3
29
|
## 0.17.0
|
|
4
30
|
|
|
5
31
|
### Patch Changes
|
package/dist/index.cjs
CHANGED
|
@@ -193,7 +193,25 @@ function viewBoxOf(diagram) {
|
|
|
193
193
|
for (const vector of diagram.vectors ?? []) {
|
|
194
194
|
const start = vector.from ?? diagram.bodies?.[0]?.at ?? [0, 0];
|
|
195
195
|
note(start);
|
|
196
|
-
|
|
196
|
+
const tip = tipOf(vector, start);
|
|
197
|
+
note(tip);
|
|
198
|
+
if (vector.label) {
|
|
199
|
+
const lx = tip[0] + (tip[0] - start[0]) * .08 + 8;
|
|
200
|
+
const ly = tip[1] + (tip[1] - start[1]) * .08;
|
|
201
|
+
note([lx, ly]);
|
|
202
|
+
note([lx + textWidth(vector.label), ly + LABEL_HEIGHT]);
|
|
203
|
+
note([lx, ly - LABEL_HEIGHT]);
|
|
204
|
+
}
|
|
205
|
+
}
|
|
206
|
+
for (const angle of diagram.angles ?? []) {
|
|
207
|
+
const radius = angle.radius ?? 28;
|
|
208
|
+
const reach = radius + (angle.label ? ANGLE_LABEL_OFFSET + textWidth(angle.label) : 0);
|
|
209
|
+
note([angle.at[0] - reach, angle.at[1] - reach]);
|
|
210
|
+
note([angle.at[0] + reach, angle.at[1] + reach]);
|
|
211
|
+
}
|
|
212
|
+
for (const surface of diagram.surfaces ?? []) {
|
|
213
|
+
if (!surface.hatch) continue;
|
|
214
|
+
note([Math.min(surface.from[0], surface.to[0]) - HATCH_REACH, Math.min(surface.from[1], surface.to[1]) - HATCH_REACH]);
|
|
197
215
|
}
|
|
198
216
|
if (xs.length === 0) return [
|
|
199
217
|
0,
|
|
@@ -209,6 +227,24 @@ function viewBoxOf(diagram) {
|
|
|
209
227
|
Math.max(...ys) + pad
|
|
210
228
|
];
|
|
211
229
|
}
|
|
230
|
+
/** How far past the arc a label sits, as the renderer places it. */
|
|
231
|
+
const ANGLE_LABEL_OFFSET = 14;
|
|
232
|
+
/** How far the hatching hangs off a surface, as the renderer draws it. */
|
|
233
|
+
const HATCH_REACH = 15;
|
|
234
|
+
/** One line of label text, in the same units the diagram is drawn in. */
|
|
235
|
+
const LABEL_HEIGHT = 14;
|
|
236
|
+
/**
|
|
237
|
+
* Roughly how wide a label will be.
|
|
238
|
+
*
|
|
239
|
+
* An estimate on purpose: measuring text needs a DOM, and this renders to a string on whatever runs it.
|
|
240
|
+
* Wide-erring — CJK counted at a full em, Latin at half — because a box slightly too big shows white
|
|
241
|
+
* space, and a box slightly too small cuts a word off.
|
|
242
|
+
*/
|
|
243
|
+
function textWidth(label) {
|
|
244
|
+
let width = 0;
|
|
245
|
+
for (const character of label) width += /[\u3000-\u9fff\uff00-\uffef]/.test(character) ? LABEL_HEIGHT : LABEL_HEIGHT * .55;
|
|
246
|
+
return width;
|
|
247
|
+
}
|
|
212
248
|
/** Where a vector ends, whether it was given as a point or as a magnitude and angle. */
|
|
213
249
|
function tipOf(vector, start) {
|
|
214
250
|
if (vector.to) return vector.to;
|
package/dist/index.js
CHANGED
|
@@ -191,7 +191,25 @@ function viewBoxOf(diagram) {
|
|
|
191
191
|
for (const vector of diagram.vectors ?? []) {
|
|
192
192
|
const start = vector.from ?? diagram.bodies?.[0]?.at ?? [0, 0];
|
|
193
193
|
note(start);
|
|
194
|
-
|
|
194
|
+
const tip = tipOf(vector, start);
|
|
195
|
+
note(tip);
|
|
196
|
+
if (vector.label) {
|
|
197
|
+
const lx = tip[0] + (tip[0] - start[0]) * .08 + 8;
|
|
198
|
+
const ly = tip[1] + (tip[1] - start[1]) * .08;
|
|
199
|
+
note([lx, ly]);
|
|
200
|
+
note([lx + textWidth(vector.label), ly + LABEL_HEIGHT]);
|
|
201
|
+
note([lx, ly - LABEL_HEIGHT]);
|
|
202
|
+
}
|
|
203
|
+
}
|
|
204
|
+
for (const angle of diagram.angles ?? []) {
|
|
205
|
+
const radius = angle.radius ?? 28;
|
|
206
|
+
const reach = radius + (angle.label ? ANGLE_LABEL_OFFSET + textWidth(angle.label) : 0);
|
|
207
|
+
note([angle.at[0] - reach, angle.at[1] - reach]);
|
|
208
|
+
note([angle.at[0] + reach, angle.at[1] + reach]);
|
|
209
|
+
}
|
|
210
|
+
for (const surface of diagram.surfaces ?? []) {
|
|
211
|
+
if (!surface.hatch) continue;
|
|
212
|
+
note([Math.min(surface.from[0], surface.to[0]) - HATCH_REACH, Math.min(surface.from[1], surface.to[1]) - HATCH_REACH]);
|
|
195
213
|
}
|
|
196
214
|
if (xs.length === 0) return [
|
|
197
215
|
0,
|
|
@@ -207,6 +225,24 @@ function viewBoxOf(diagram) {
|
|
|
207
225
|
Math.max(...ys) + pad
|
|
208
226
|
];
|
|
209
227
|
}
|
|
228
|
+
/** How far past the arc a label sits, as the renderer places it. */
|
|
229
|
+
const ANGLE_LABEL_OFFSET = 14;
|
|
230
|
+
/** How far the hatching hangs off a surface, as the renderer draws it. */
|
|
231
|
+
const HATCH_REACH = 15;
|
|
232
|
+
/** One line of label text, in the same units the diagram is drawn in. */
|
|
233
|
+
const LABEL_HEIGHT = 14;
|
|
234
|
+
/**
|
|
235
|
+
* Roughly how wide a label will be.
|
|
236
|
+
*
|
|
237
|
+
* An estimate on purpose: measuring text needs a DOM, and this renders to a string on whatever runs it.
|
|
238
|
+
* Wide-erring — CJK counted at a full em, Latin at half — because a box slightly too big shows white
|
|
239
|
+
* space, and a box slightly too small cuts a word off.
|
|
240
|
+
*/
|
|
241
|
+
function textWidth(label) {
|
|
242
|
+
let width = 0;
|
|
243
|
+
for (const character of label) width += /[\u3000-\u9fff\uff00-\uffef]/.test(character) ? LABEL_HEIGHT : LABEL_HEIGHT * .55;
|
|
244
|
+
return width;
|
|
245
|
+
}
|
|
210
246
|
/** Where a vector ends, whether it was given as a point or as a magnitude and angle. */
|
|
211
247
|
function tipOf(vector, start) {
|
|
212
248
|
if (vector.to) return vector.to;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@ai-gui/plugin-physics",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.18.0",
|
|
4
4
|
"description": "Force and vector diagrams for teaching mechanics, rendered as SVG from a declarative block.",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"llm",
|
|
@@ -54,7 +54,7 @@
|
|
|
54
54
|
"access": "public"
|
|
55
55
|
},
|
|
56
56
|
"dependencies": {
|
|
57
|
-
"@ai-gui/core": "0.
|
|
57
|
+
"@ai-gui/core": "0.18.0"
|
|
58
58
|
},
|
|
59
59
|
"scripts": {
|
|
60
60
|
"build": "tsdown",
|