fluidcad 0.0.36 → 0.0.37
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/LICENSE.txt +21 -504
- package/README.md +1 -1
- package/lib/dist/common/edge.d.ts +1 -1
- package/lib/dist/common/face.d.ts +1 -1
- package/lib/dist/common/scene-object.d.ts +6 -0
- package/lib/dist/common/scene-object.js +8 -0
- package/lib/dist/common/shape-factory.d.ts +1 -1
- package/lib/dist/common/shape-history-tracker.d.ts +1 -1
- package/lib/dist/common/shape.d.ts +1 -1
- package/lib/dist/common/solid.d.ts +1 -1
- package/lib/dist/common/transformable-primitive.d.ts +12 -1
- package/lib/dist/common/transformable-primitive.js +27 -0
- package/lib/dist/common/vertex.d.ts +1 -1
- package/lib/dist/common/wire.d.ts +1 -1
- package/lib/dist/core/2d/index.d.ts +1 -0
- package/lib/dist/core/2d/index.js +1 -0
- package/lib/dist/core/2d/text.d.ts +30 -0
- package/lib/dist/core/2d/text.js +37 -0
- package/lib/dist/core/helix.d.ts +20 -0
- package/lib/dist/core/helix.js +36 -0
- package/lib/dist/core/index.d.ts +3 -1
- package/lib/dist/core/index.js +2 -0
- package/lib/dist/core/interfaces.d.ts +180 -0
- package/lib/dist/core/wrap.d.ts +17 -0
- package/lib/dist/core/wrap.js +39 -0
- package/lib/dist/features/2d/text.d.ts +67 -0
- package/lib/dist/features/2d/text.js +320 -0
- package/lib/dist/features/cylinder.d.ts +3 -1
- package/lib/dist/features/cylinder.js +5 -2
- package/lib/dist/features/extrude-base.d.ts +1 -0
- package/lib/dist/features/extrude-to-face.d.ts +1 -0
- package/lib/dist/features/extrude-to-face.js +6 -0
- package/lib/dist/features/fillet.d.ts +1 -1
- package/lib/dist/features/helix.d.ts +41 -0
- package/lib/dist/features/helix.js +337 -0
- package/lib/dist/features/select.js +32 -8
- package/lib/dist/features/simple-extruder.d.ts +1 -1
- package/lib/dist/features/simple-extruder.js +7 -2
- package/lib/dist/features/sphere.d.ts +3 -1
- package/lib/dist/features/sphere.js +5 -2
- package/lib/dist/features/sweep.js +7 -2
- package/lib/dist/features/wrap.d.ts +39 -0
- package/lib/dist/features/wrap.js +116 -0
- package/lib/dist/filters/edge/belongs-to-face.d.ts +3 -1
- package/lib/dist/filters/edge/belongs-to-face.js +14 -10
- package/lib/dist/filters/filter.d.ts +1 -1
- package/lib/dist/filters/from-object.d.ts +1 -1
- package/lib/dist/filters/tangent-expander.d.ts +1 -1
- package/lib/dist/filters/tangent-expander.js +57 -40
- package/lib/dist/helpers/scene-helpers.d.ts +2 -0
- package/lib/dist/helpers/scene-helpers.js +1 -1
- package/lib/dist/index.d.ts +2 -0
- package/lib/dist/index.js +3 -1
- package/lib/dist/io/file-import.d.ts +7 -0
- package/lib/dist/io/file-import.js +28 -1
- package/lib/dist/io/font-registry.d.ts +45 -0
- package/lib/dist/io/font-registry.js +272 -0
- package/lib/dist/math/bspline-interpolation.d.ts +29 -0
- package/lib/dist/math/bspline-interpolation.js +194 -0
- package/lib/dist/oc/boolean-ops.d.ts +3 -1
- package/lib/dist/oc/boolean-ops.js +15 -1
- package/lib/dist/oc/color-transfer.d.ts +1 -1
- package/lib/dist/oc/constraints/constraint-helpers.d.ts +4 -4
- package/lib/dist/oc/constraints/curve/tangent-circle-solver.js +10 -9
- package/lib/dist/oc/constraints/curve/tangent-line-solver.js +5 -6
- package/lib/dist/oc/convert.d.ts +1 -1
- package/lib/dist/oc/draft-ops.d.ts +1 -1
- package/lib/dist/oc/edge-ops.d.ts +2 -2
- package/lib/dist/oc/edge-ops.js +13 -14
- package/lib/dist/oc/edge-props.d.ts +1 -1
- package/lib/dist/oc/edge-query.d.ts +1 -1
- package/lib/dist/oc/edge-query.js +3 -8
- package/lib/dist/oc/errors.d.ts +8 -0
- package/lib/dist/oc/errors.js +27 -0
- package/lib/dist/oc/explorer.d.ts +2 -2
- package/lib/dist/oc/extrude-ops.d.ts +28 -2
- package/lib/dist/oc/extrude-ops.js +56 -7
- package/lib/dist/oc/face-ops.d.ts +2 -1
- package/lib/dist/oc/face-ops.js +11 -0
- package/lib/dist/oc/face-props.d.ts +1 -1
- package/lib/dist/oc/face-query.d.ts +12 -1
- package/lib/dist/oc/face-query.js +39 -0
- package/lib/dist/oc/fillet-ops.d.ts +1 -1
- package/lib/dist/oc/fillet-ops.js +4 -4
- package/lib/dist/oc/geometry.d.ts +1 -1
- package/lib/dist/oc/geometry.js +12 -14
- package/lib/dist/oc/helix-ops.d.ts +37 -0
- package/lib/dist/oc/helix-ops.js +88 -0
- package/lib/dist/oc/hit-test.d.ts +1 -1
- package/lib/dist/oc/index.d.ts +4 -0
- package/lib/dist/oc/index.js +2 -0
- package/lib/dist/oc/init.d.ts +1 -1
- package/lib/dist/oc/init.js +1 -1
- package/lib/dist/oc/intersection.js +1 -1
- package/lib/dist/oc/io.d.ts +6 -6
- package/lib/dist/oc/io.js +31 -24
- package/lib/dist/oc/measure/classify.d.ts +34 -0
- package/lib/dist/oc/measure/classify.js +246 -0
- package/lib/dist/oc/measure/measure-ops.d.ts +9 -0
- package/lib/dist/oc/measure/measure-ops.js +210 -0
- package/lib/dist/oc/measure/measure-types.d.ts +39 -0
- package/lib/dist/oc/measure/measure-types.js +1 -0
- package/lib/dist/oc/measure/sampling.d.ts +9 -0
- package/lib/dist/oc/measure/sampling.js +77 -0
- package/lib/dist/oc/measure/vec.d.ts +13 -0
- package/lib/dist/oc/measure/vec.js +23 -0
- package/lib/dist/oc/mesh.d.ts +1 -1
- package/lib/dist/oc/mesh.js +40 -28
- package/lib/dist/oc/path-sampler.d.ts +29 -0
- package/lib/dist/oc/path-sampler.js +63 -0
- package/lib/dist/oc/props.d.ts +1 -1
- package/lib/dist/oc/props.js +4 -1
- package/lib/dist/oc/shape-hash.d.ts +26 -0
- package/lib/dist/oc/shape-hash.js +32 -0
- package/lib/dist/oc/shape-ops.d.ts +5 -3
- package/lib/dist/oc/shape-ops.js +6 -5
- package/lib/dist/oc/sweep-ops.d.ts +22 -1
- package/lib/dist/oc/sweep-ops.js +206 -18
- package/lib/dist/oc/text-outline.d.ts +62 -0
- package/lib/dist/oc/text-outline.js +212 -0
- package/lib/dist/oc/topology-index.d.ts +1 -1
- package/lib/dist/oc/vertex-ops.d.ts +1 -1
- package/lib/dist/oc/wire-ops.d.ts +1 -1
- package/lib/dist/oc/wire-ops.js +1 -1
- package/lib/dist/oc/wrap-development.d.ts +105 -0
- package/lib/dist/oc/wrap-development.js +179 -0
- package/lib/dist/oc/wrap-ops.d.ts +100 -0
- package/lib/dist/oc/wrap-ops.js +406 -0
- package/lib/dist/rendering/render-solid.js +10 -2
- package/lib/dist/scene-manager.d.ts +2 -0
- package/lib/dist/scene-manager.js +29 -0
- package/lib/dist/tests/features/cylinder-curve-filter.test.js +3 -3
- package/lib/dist/tests/features/extrude-to-face.test.js +38 -1
- package/lib/dist/tests/features/helix.test.d.ts +1 -0
- package/lib/dist/tests/features/helix.test.js +295 -0
- package/lib/dist/tests/features/repeat-primitive.test.d.ts +1 -0
- package/lib/dist/tests/features/repeat-primitive.test.js +60 -0
- package/lib/dist/tests/features/rib.test.js +6 -1
- package/lib/dist/tests/features/sweep.test.js +125 -1
- package/lib/dist/tests/features/text.test.d.ts +1 -0
- package/lib/dist/tests/features/text.test.js +347 -0
- package/lib/dist/tests/features/wrap-development.test.d.ts +1 -0
- package/lib/dist/tests/features/wrap-development.test.js +130 -0
- package/lib/dist/tests/features/wrap-extruded-target.test.d.ts +1 -0
- package/lib/dist/tests/features/wrap-extruded-target.test.js +106 -0
- package/lib/dist/tests/features/wrap-repeat.test.d.ts +1 -0
- package/lib/dist/tests/features/wrap-repeat.test.js +93 -0
- package/lib/dist/tests/features/wrap.test.d.ts +1 -0
- package/lib/dist/tests/features/wrap.test.js +331 -0
- package/lib/dist/tests/math/bspline-interpolation.test.d.ts +1 -0
- package/lib/dist/tests/math/bspline-interpolation.test.js +119 -0
- package/lib/dist/tests/measure.test.d.ts +1 -0
- package/lib/dist/tests/measure.test.js +288 -0
- package/lib/dist/tsconfig.tsbuildinfo +1 -1
- package/llm-docs/api/helix.md +64 -0
- package/llm-docs/api/index.json +11 -2
- package/llm-docs/api/text.md +52 -0
- package/llm-docs/api/types/helix.md +105 -0
- package/llm-docs/api/types/text.md +138 -0
- package/llm-docs/api/types/wrap.md +131 -0
- package/llm-docs/api/wrap.md +62 -0
- package/llm-docs/index.json +121 -1
- package/mcp/dist/server.js +20 -1
- package/mcp/dist/tools/inspection.d.ts +17 -0
- package/mcp/dist/tools/inspection.js +14 -0
- package/package.json +7 -3
- package/server/dist/fluidcad-server.d.ts +10 -0
- package/server/dist/fluidcad-server.js +10 -0
- package/server/dist/index.js +4 -2
- package/server/dist/preferences.d.ts +4 -0
- package/server/dist/preferences.js +2 -0
- package/server/dist/routes/measure.d.ts +3 -0
- package/server/dist/routes/measure.js +32 -0
- package/server/dist/routes/preferences.js +6 -0
- package/server/dist/routes/sketch-edits.js +2 -1
- package/ui/dist/assets/{index-CDJmUpFI.css → index-dAFdg2Un.css} +1 -1
- package/ui/dist/assets/{index-MRqwG9Vh.js → index-no7mtr5s.js} +149 -102
- package/ui/dist/index.html +2 -2
package/llm-docs/index.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"schemaVersion": 1,
|
|
3
|
-
"generatedAt": "2026-06-
|
|
3
|
+
"generatedAt": "2026-06-12T18:19:00.445Z",
|
|
4
4
|
"docs": [
|
|
5
5
|
{
|
|
6
6
|
"id": "api/arc",
|
|
@@ -394,6 +394,27 @@
|
|
|
394
394
|
"file": "api/fillet.md",
|
|
395
395
|
"bodyLength": 1243
|
|
396
396
|
},
|
|
397
|
+
{
|
|
398
|
+
"id": "api/helix",
|
|
399
|
+
"title": "helix(axis | source)",
|
|
400
|
+
"summary": "Creates a helical wire around an axis or derived from existing geometry (cylindrical/conical face, line or circular edge) — the path for springs, threads, and coils. Sweep a profile along it to make material.",
|
|
401
|
+
"tags": [
|
|
402
|
+
"api",
|
|
403
|
+
"3d",
|
|
404
|
+
"wire"
|
|
405
|
+
],
|
|
406
|
+
"symbols": [
|
|
407
|
+
"helix"
|
|
408
|
+
],
|
|
409
|
+
"seeAlso": [
|
|
410
|
+
"api/sweep",
|
|
411
|
+
"api/axis",
|
|
412
|
+
"api/select",
|
|
413
|
+
"api/types/helix"
|
|
414
|
+
],
|
|
415
|
+
"file": "api/helix.md",
|
|
416
|
+
"bodyLength": 2133
|
|
417
|
+
},
|
|
397
418
|
{
|
|
398
419
|
"id": "api/line",
|
|
399
420
|
"title": "line(end) / line(start, end)",
|
|
@@ -887,6 +908,27 @@
|
|
|
887
908
|
"file": "api/tcircle.md",
|
|
888
909
|
"bodyLength": 755
|
|
889
910
|
},
|
|
911
|
+
{
|
|
912
|
+
"id": "api/text",
|
|
913
|
+
"title": "text(string) / text(plane, string) / text(string, path)",
|
|
914
|
+
"summary": "Renders a text string as sketch geometry — glyph outlines that extrude, wrap, or follow a path like any other profile.",
|
|
915
|
+
"tags": [
|
|
916
|
+
"api",
|
|
917
|
+
"2d",
|
|
918
|
+
"sketch"
|
|
919
|
+
],
|
|
920
|
+
"symbols": [
|
|
921
|
+
"text"
|
|
922
|
+
],
|
|
923
|
+
"seeAlso": [
|
|
924
|
+
"api/sketch",
|
|
925
|
+
"api/wrap",
|
|
926
|
+
"api/extrude",
|
|
927
|
+
"api/types/text"
|
|
928
|
+
],
|
|
929
|
+
"file": "api/text.md",
|
|
930
|
+
"bodyLength": 1591
|
|
931
|
+
},
|
|
890
932
|
{
|
|
891
933
|
"id": "api/tline",
|
|
892
934
|
"title": "tLine — tangent line",
|
|
@@ -1187,6 +1229,25 @@
|
|
|
1187
1229
|
"file": "api/types/geometry.md",
|
|
1188
1230
|
"bodyLength": 909
|
|
1189
1231
|
},
|
|
1232
|
+
{
|
|
1233
|
+
"id": "api/types/helix",
|
|
1234
|
+
"title": "Helix",
|
|
1235
|
+
"summary": "A 3D helix wire — a single edge that traces a helix curve on a cylindrical or conical surface.",
|
|
1236
|
+
"tags": [
|
|
1237
|
+
"api",
|
|
1238
|
+
"type",
|
|
1239
|
+
"interface"
|
|
1240
|
+
],
|
|
1241
|
+
"symbols": [
|
|
1242
|
+
"Helix",
|
|
1243
|
+
"IHelix"
|
|
1244
|
+
],
|
|
1245
|
+
"seeAlso": [
|
|
1246
|
+
"api/types/scene-object"
|
|
1247
|
+
],
|
|
1248
|
+
"file": "api/types/helix.md",
|
|
1249
|
+
"bodyLength": 2680
|
|
1250
|
+
},
|
|
1190
1251
|
{
|
|
1191
1252
|
"id": "api/types/hline",
|
|
1192
1253
|
"title": "HLine",
|
|
@@ -1585,6 +1646,25 @@
|
|
|
1585
1646
|
"file": "api/types/tangent-arc-two-objects.md",
|
|
1586
1647
|
"bodyLength": 847
|
|
1587
1648
|
},
|
|
1649
|
+
{
|
|
1650
|
+
"id": "api/types/text",
|
|
1651
|
+
"title": "Text",
|
|
1652
|
+
"summary": "The Text type. Extends ExtrudableGeometry; adds 11 methods.",
|
|
1653
|
+
"tags": [
|
|
1654
|
+
"api",
|
|
1655
|
+
"type",
|
|
1656
|
+
"interface"
|
|
1657
|
+
],
|
|
1658
|
+
"symbols": [
|
|
1659
|
+
"Text",
|
|
1660
|
+
"IText"
|
|
1661
|
+
],
|
|
1662
|
+
"seeAlso": [
|
|
1663
|
+
"api/types/extrudable-geometry"
|
|
1664
|
+
],
|
|
1665
|
+
"file": "api/types/text.md",
|
|
1666
|
+
"bodyLength": 4156
|
|
1667
|
+
},
|
|
1588
1668
|
{
|
|
1589
1669
|
"id": "api/types/transformable",
|
|
1590
1670
|
"title": "Transformable",
|
|
@@ -1684,6 +1764,46 @@
|
|
|
1684
1764
|
"file": "api/types/vline.md",
|
|
1685
1765
|
"bodyLength": 641
|
|
1686
1766
|
},
|
|
1767
|
+
{
|
|
1768
|
+
"id": "api/types/wrap",
|
|
1769
|
+
"title": "Wrap",
|
|
1770
|
+
"summary": "The Wrap type. Extends BooleanOperation; adds 10 methods.",
|
|
1771
|
+
"tags": [
|
|
1772
|
+
"api",
|
|
1773
|
+
"type",
|
|
1774
|
+
"interface"
|
|
1775
|
+
],
|
|
1776
|
+
"symbols": [
|
|
1777
|
+
"Wrap",
|
|
1778
|
+
"IWrap"
|
|
1779
|
+
],
|
|
1780
|
+
"seeAlso": [
|
|
1781
|
+
"api/types/boolean-operation"
|
|
1782
|
+
],
|
|
1783
|
+
"file": "api/types/wrap.md",
|
|
1784
|
+
"bodyLength": 3888
|
|
1785
|
+
},
|
|
1786
|
+
{
|
|
1787
|
+
"id": "api/wrap",
|
|
1788
|
+
"title": "wrap(thickness, sketch, face)",
|
|
1789
|
+
"summary": "Develops a sketch onto a cylindrical or conical face and raises it by a thickness — embossed or engraved labels, logos, and features that follow a curved wall.",
|
|
1790
|
+
"tags": [
|
|
1791
|
+
"api",
|
|
1792
|
+
"3d",
|
|
1793
|
+
"solid"
|
|
1794
|
+
],
|
|
1795
|
+
"symbols": [
|
|
1796
|
+
"wrap"
|
|
1797
|
+
],
|
|
1798
|
+
"seeAlso": [
|
|
1799
|
+
"api/sketch",
|
|
1800
|
+
"api/types/text",
|
|
1801
|
+
"api/select",
|
|
1802
|
+
"api/extrude"
|
|
1803
|
+
],
|
|
1804
|
+
"file": "api/wrap.md",
|
|
1805
|
+
"bodyLength": 2024
|
|
1806
|
+
},
|
|
1687
1807
|
{
|
|
1688
1808
|
"id": "concepts/coordinate-system",
|
|
1689
1809
|
"title": "Coordinate systems and sketch axes",
|
package/mcp/dist/server.js
CHANGED
|
@@ -11,7 +11,7 @@ import { StdioServerTransport } from '@modelcontextprotocol/sdk/server/stdio.js'
|
|
|
11
11
|
import { z } from 'zod';
|
|
12
12
|
import { listWorkspaces } from "./tools/workspaces.js";
|
|
13
13
|
import { getApiSignature, getTypeDefinition, listDocs, readDoc, searchDocs, } from "./tools/docs.js";
|
|
14
|
-
import { getCompileError, getEdgeProperties, getFaceProperties, getSceneSummary, getShapeProperties, hitTest, listShapes, } from "./tools/inspection.js";
|
|
14
|
+
import { getCompileError, getEdgeProperties, getFaceProperties, getSceneSummary, getShapeProperties, hitTest, listShapes, measure, } from "./tools/inspection.js";
|
|
15
15
|
import { getCameraState, screenshot, screenshotMulti, screenshotShape, } from "./tools/screenshot.js";
|
|
16
16
|
import { waitForIdle } from "./tools/coordination.js";
|
|
17
17
|
import { editRange, listFluidFiles, readFile, writeFile, } from "./tools/source.js";
|
|
@@ -186,6 +186,25 @@ export function buildServer(options = {}) {
|
|
|
186
186
|
edgeIndex: edgeIndexArg,
|
|
187
187
|
},
|
|
188
188
|
}, async ({ workspace, shapeId, edgeIndex }) => toMcp(await getEdgeProperties({ workspace, shapeId, edgeIndex })));
|
|
189
|
+
const measureEntityArg = z.object({
|
|
190
|
+
shapeId: shapeIdArg,
|
|
191
|
+
kind: z.enum(['face', 'edge']).describe('Whether the index refers to a face or an edge of the shape.'),
|
|
192
|
+
index: z.number().int().nonnegative().describe('Zero-based face/edge index inside the shape.'),
|
|
193
|
+
});
|
|
194
|
+
server.registerTool('measure', {
|
|
195
|
+
title: 'Measure distances and angles between faces/edges',
|
|
196
|
+
description: 'Measures the selected faces/edges like a CAD measure tool. One entity returns its area/length; two entities ' +
|
|
197
|
+
'return min/max distance with their realizing points, plus parallel/center/axis distance and angle when the ' +
|
|
198
|
+
'geometry relation supports them. `primary` names the headline value. All lengths are mm, angles deg.',
|
|
199
|
+
inputSchema: {
|
|
200
|
+
...workspaceArg,
|
|
201
|
+
entities: z
|
|
202
|
+
.array(measureEntityArg)
|
|
203
|
+
.min(1)
|
|
204
|
+
.max(8)
|
|
205
|
+
.describe('Faces/edges to measure (1-8). Pairwise measurements are computed when exactly 2 are given.'),
|
|
206
|
+
},
|
|
207
|
+
}, async ({ workspace, entities }) => toMcp(await measure({ workspace, entities })));
|
|
189
208
|
const namedViewArg = z.enum([
|
|
190
209
|
'front', 'back', 'left', 'right', 'top', 'bottom',
|
|
191
210
|
'iso-ftr', 'iso-fbr', 'iso-ftl', 'iso-fbl',
|
|
@@ -73,3 +73,20 @@ export declare function hitTest(input: HitTestInput): Promise<{
|
|
|
73
73
|
ok: true;
|
|
74
74
|
data: unknown;
|
|
75
75
|
}>;
|
|
76
|
+
export type MeasureEntityInput = {
|
|
77
|
+
shapeId: string;
|
|
78
|
+
kind: 'face' | 'edge';
|
|
79
|
+
index: number;
|
|
80
|
+
};
|
|
81
|
+
export type MeasureInput = WorkspaceArg & {
|
|
82
|
+
entities: MeasureEntityInput[];
|
|
83
|
+
};
|
|
84
|
+
export declare function measure(input: MeasureInput): Promise<{
|
|
85
|
+
ok: false;
|
|
86
|
+
code: import("../types.ts").ToolErrorCode;
|
|
87
|
+
message: string;
|
|
88
|
+
details?: unknown;
|
|
89
|
+
} | {
|
|
90
|
+
ok: true;
|
|
91
|
+
data: unknown;
|
|
92
|
+
}>;
|
|
@@ -114,6 +114,20 @@ export async function hitTest(input) {
|
|
|
114
114
|
};
|
|
115
115
|
return callWithClient(input, (client) => client.postJson('/api/hit-test', body));
|
|
116
116
|
}
|
|
117
|
+
export async function measure(input) {
|
|
118
|
+
const entities = input?.entities;
|
|
119
|
+
if (!Array.isArray(entities) || entities.length < 1 || entities.length > 8) {
|
|
120
|
+
return err('invalid-input', '`entities` must be an array of 1-8 face/edge references.');
|
|
121
|
+
}
|
|
122
|
+
for (const entity of entities) {
|
|
123
|
+
const validKind = entity?.kind === 'face' || entity?.kind === 'edge';
|
|
124
|
+
const validIndex = typeof entity?.index === 'number' && Number.isInteger(entity.index) && entity.index >= 0;
|
|
125
|
+
if (!entity || typeof entity.shapeId !== 'string' || !entity.shapeId || !validKind || !validIndex) {
|
|
126
|
+
return err('invalid-input', 'Each entity needs a `shapeId`, a `kind` (face|edge) and a non-negative `index`.');
|
|
127
|
+
}
|
|
128
|
+
}
|
|
129
|
+
return callWithClient(input, (client) => client.postJson('/api/measure', { entities }));
|
|
130
|
+
}
|
|
117
131
|
function isVec3(value) {
|
|
118
132
|
return (Array.isArray(value) &&
|
|
119
133
|
value.length === 3 &&
|
package/package.json
CHANGED
|
@@ -1,8 +1,9 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "fluidcad",
|
|
3
|
-
"version": "0.0.
|
|
3
|
+
"version": "0.0.37",
|
|
4
4
|
"description": "Parametric CAD modeling library using javascript",
|
|
5
5
|
"author": "Marwan Aouida <contact@marwan.dev>",
|
|
6
|
+
"license": "MIT",
|
|
6
7
|
"homepage": "https://fluidcad.io",
|
|
7
8
|
"repository": {
|
|
8
9
|
"type": "git",
|
|
@@ -69,10 +70,12 @@
|
|
|
69
70
|
"commander": "^14.0.3",
|
|
70
71
|
"esbuild": "^0.27.7",
|
|
71
72
|
"express": "^5.2.1",
|
|
73
|
+
"fontkit": "^2.0.4",
|
|
74
|
+
"get-system-fonts": "^2.0.2",
|
|
75
|
+
"iconoir": "^7.11.0",
|
|
72
76
|
"ignore": "^5.3.2",
|
|
73
77
|
"jszip": "^3.10.1",
|
|
74
|
-
"
|
|
75
|
-
"occjs-wrapper": "npm:occjs-fluidcad@9.0.0",
|
|
78
|
+
"ocjs-fluidcad": "^1.1.0",
|
|
76
79
|
"open": "^11.0.0",
|
|
77
80
|
"stacktrace-parser": "^0.1.11",
|
|
78
81
|
"tree-sitter-wasms": "^0.1.13",
|
|
@@ -87,6 +90,7 @@
|
|
|
87
90
|
"@tabler/icons": "^3.40.0",
|
|
88
91
|
"@tailwindcss/vite": "^4.2.2",
|
|
89
92
|
"@types/express": "^5.0.6",
|
|
93
|
+
"@types/fontkit": "^2.0.9",
|
|
90
94
|
"@types/js-yaml": "^4.0.9",
|
|
91
95
|
"@types/node": "^22.14.1",
|
|
92
96
|
"@types/three": "^0.180.0",
|
|
@@ -11,6 +11,11 @@ type SceneManager = {
|
|
|
11
11
|
getShapeProperties(scene: any, shapeId: string): any;
|
|
12
12
|
getFaceProperties(scene: any, shapeId: string, faceIndex: number): any;
|
|
13
13
|
getEdgeProperties(scene: any, shapeId: string, edgeIndex: number): any;
|
|
14
|
+
measure(scene: any, refs: {
|
|
15
|
+
shapeId: string;
|
|
16
|
+
kind: 'face' | 'edge';
|
|
17
|
+
index: number;
|
|
18
|
+
}[]): any;
|
|
14
19
|
hitTest(scene: any, shapeId: string, rayOrigin: [number, number, number], rayDir: [number, number, number], edgeThreshold: number): any;
|
|
15
20
|
exportShapes(scene: any, shapeIds: string[], options: {
|
|
16
21
|
format: 'step' | 'stl';
|
|
@@ -115,6 +120,11 @@ export declare class FluidCadServer {
|
|
|
115
120
|
getShapeProperties(shapeId: string): any;
|
|
116
121
|
getFaceProperties(shapeId: string, faceIndex: number): any;
|
|
117
122
|
getEdgeProperties(shapeId: string, edgeIndex: number): any;
|
|
123
|
+
measure(refs: {
|
|
124
|
+
shapeId: string;
|
|
125
|
+
kind: 'face' | 'edge';
|
|
126
|
+
index: number;
|
|
127
|
+
}[]): any;
|
|
118
128
|
exportShapes(shapeIds: string[], options: {
|
|
119
129
|
format: 'step' | 'stl';
|
|
120
130
|
includeColors?: boolean;
|
|
@@ -285,6 +285,16 @@ export class FluidCadServer {
|
|
|
285
285
|
}
|
|
286
286
|
return this.sceneManager.getEdgeProperties(scene, shapeId, edgeIndex);
|
|
287
287
|
}
|
|
288
|
+
measure(refs) {
|
|
289
|
+
if (!this.sceneManager) {
|
|
290
|
+
return null;
|
|
291
|
+
}
|
|
292
|
+
const scene = this.previousScenes.get(this.currentFileName);
|
|
293
|
+
if (!scene) {
|
|
294
|
+
return null;
|
|
295
|
+
}
|
|
296
|
+
return this.sceneManager.measure(scene, refs);
|
|
297
|
+
}
|
|
288
298
|
exportShapes(shapeIds, options) {
|
|
289
299
|
if (!this.sceneManager) {
|
|
290
300
|
return null;
|
package/server/dist/index.js
CHANGED
|
@@ -7,6 +7,7 @@ import { createServerCore } from "./server-core.js";
|
|
|
7
7
|
import { createPropertiesRouter } from "./routes/properties.js";
|
|
8
8
|
import { createParamsRouter } from "./routes/params.js";
|
|
9
9
|
import { createHitTestRouter } from "./routes/hit-test.js";
|
|
10
|
+
import { createMeasureRouter } from "./routes/measure.js";
|
|
10
11
|
import { createTimelineRouter } from "./routes/timeline.js";
|
|
11
12
|
import { createSketchEditsRouter } from "./routes/sketch-edits.js";
|
|
12
13
|
import { createExportRouter } from "./routes/export.js";
|
|
@@ -21,7 +22,7 @@ import { createPackRouter } from "./routes/pack.js";
|
|
|
21
22
|
import { normalizePath } from "./normalize-path.js";
|
|
22
23
|
import { writeInstanceFile, deleteInstanceFile } from "./instance-file.js";
|
|
23
24
|
import { addInstance, removeInstance } from "./global-registry.js";
|
|
24
|
-
import { extractSourceLocation } from '../../lib/dist/index.js';
|
|
25
|
+
import { extractSourceLocation, describeOcException } from '../../lib/dist/index.js';
|
|
25
26
|
const PORT = parseInt(process.env.FLUIDCAD_SERVER_PORT || '3100', 10);
|
|
26
27
|
const WORKSPACE_PATH = normalizePath(process.env.FLUIDCAD_WORKSPACE_PATH || '');
|
|
27
28
|
const UI_DIST = path.resolve(import.meta.dirname, '../../ui/dist');
|
|
@@ -72,6 +73,7 @@ app.use('/api', createHealthRouter({
|
|
|
72
73
|
app.use('/api', createPropertiesRouter(fluidCadServer));
|
|
73
74
|
app.use('/api', createParamsRouter(fluidCadServer, sendToExtension, broadcastToUI));
|
|
74
75
|
app.use('/api', createHitTestRouter(fluidCadServer));
|
|
76
|
+
app.use('/api', createMeasureRouter(fluidCadServer));
|
|
75
77
|
app.use('/api', createTimelineRouter(fluidCadServer, sendToExtension, broadcastToUI));
|
|
76
78
|
app.use('/api', createSketchEditsRouter(fluidCadServer, sendToExtension, WORKSPACE_PATH));
|
|
77
79
|
app.use('/api', createExportRouter(fluidCadServer, WORKSPACE_PATH));
|
|
@@ -252,7 +254,7 @@ async function handleExtensionMessage(msg) {
|
|
|
252
254
|
sendToExtension({ type: 'import-complete', success: true });
|
|
253
255
|
}
|
|
254
256
|
catch (err) {
|
|
255
|
-
sendToExtension({ type: 'error', message:
|
|
257
|
+
sendToExtension({ type: 'error', message: describeOcException(err) });
|
|
256
258
|
}
|
|
257
259
|
break;
|
|
258
260
|
}
|
|
@@ -1,8 +1,12 @@
|
|
|
1
|
+
export type MeasureLengthUnit = 'mm' | 'cm' | 'm' | 'in';
|
|
2
|
+
export type MeasureAngleUnit = 'deg' | 'rad';
|
|
1
3
|
export interface Preferences {
|
|
2
4
|
theme: string;
|
|
3
5
|
showGrid: boolean;
|
|
4
6
|
cameraMode: 'perspective' | 'orthographic';
|
|
5
7
|
showBuildTimings: boolean;
|
|
8
|
+
measureLengthUnit: MeasureLengthUnit;
|
|
9
|
+
measureAngleUnit: MeasureAngleUnit;
|
|
6
10
|
}
|
|
7
11
|
export declare function loadPreferences(): Promise<Preferences>;
|
|
8
12
|
export declare function savePreferences(prefs: Preferences): Promise<void>;
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
import { Router } from 'express';
|
|
2
|
+
const MAX_ENTITIES = 8;
|
|
3
|
+
export function createMeasureRouter(fluidCadServer) {
|
|
4
|
+
const router = Router();
|
|
5
|
+
router.post('/measure', (req, res) => {
|
|
6
|
+
const entities = req.body?.entities;
|
|
7
|
+
if (!Array.isArray(entities) || entities.length < 1 || entities.length > MAX_ENTITIES) {
|
|
8
|
+
res.status(400).json({ error: `entities must be an array of 1-${MAX_ENTITIES} face/edge references` });
|
|
9
|
+
return;
|
|
10
|
+
}
|
|
11
|
+
for (const entity of entities) {
|
|
12
|
+
const validKind = entity?.kind === 'face' || entity?.kind === 'edge';
|
|
13
|
+
const validIndex = Number.isInteger(entity?.index) && entity.index >= 0;
|
|
14
|
+
if (!entity || typeof entity.shapeId !== 'string' || !entity.shapeId || !validKind || !validIndex) {
|
|
15
|
+
res.status(400).json({ error: 'Each entity needs a shapeId, a kind (face|edge) and a non-negative index' });
|
|
16
|
+
return;
|
|
17
|
+
}
|
|
18
|
+
}
|
|
19
|
+
try {
|
|
20
|
+
const result = fluidCadServer.measure(entities);
|
|
21
|
+
if (!result) {
|
|
22
|
+
res.status(404).json({ error: 'Entity not found' });
|
|
23
|
+
return;
|
|
24
|
+
}
|
|
25
|
+
res.json(result);
|
|
26
|
+
}
|
|
27
|
+
catch (err) {
|
|
28
|
+
res.status(500).json({ error: err?.message ?? String(err) });
|
|
29
|
+
}
|
|
30
|
+
});
|
|
31
|
+
return router;
|
|
32
|
+
}
|
|
@@ -27,6 +27,12 @@ export function createPreferencesRouter() {
|
|
|
27
27
|
if (typeof body.showBuildTimings === 'boolean') {
|
|
28
28
|
current.showBuildTimings = body.showBuildTimings;
|
|
29
29
|
}
|
|
30
|
+
if (['mm', 'cm', 'm', 'in'].includes(body.measureLengthUnit)) {
|
|
31
|
+
current.measureLengthUnit = body.measureLengthUnit;
|
|
32
|
+
}
|
|
33
|
+
if (['deg', 'rad'].includes(body.measureAngleUnit)) {
|
|
34
|
+
current.measureAngleUnit = body.measureAngleUnit;
|
|
35
|
+
}
|
|
30
36
|
await savePreferences(current);
|
|
31
37
|
res.json(current);
|
|
32
38
|
}
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { Router } from 'express';
|
|
2
|
+
import { describeOcException } from '../../../lib/dist/index.js';
|
|
2
3
|
import { addBreakpoint, removeBreakpoint, toggleBreakpoint, clearBreakpoints, insertPoint, removePoint, addPick, removePick, setPickPoints, insertGeometryCallWithVariable, updateGeometryPosition, setLinePosition, setChainPositions, updateDimension, updateDimensionExpressionWithVariable, getDimensionExpression, extractVariablesInScope, setRectDimensions, } from "../code-editor.js";
|
|
3
4
|
const NEW_VAR_NAME_RE = /^[a-zA-Z_$][\w$]*$/;
|
|
4
5
|
function validateNewVariable(input) {
|
|
@@ -32,7 +33,7 @@ export function createSketchEditsRouter(fluidCadServer, sendToExtension, workspa
|
|
|
32
33
|
await fluidCadServer.importFile(workspacePath, fileName, data);
|
|
33
34
|
}
|
|
34
35
|
catch (err) {
|
|
35
|
-
res.status(500).json({ error:
|
|
36
|
+
res.status(500).json({ error: describeOcException(err) });
|
|
36
37
|
return;
|
|
37
38
|
}
|
|
38
39
|
const loadName = fileName.replace(/\.(step|stp)$/i, '');
|