@cadit-app/image-extrude 0.1.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.
Files changed (46) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +99 -0
  3. package/cadit.json +20 -0
  4. package/dist/cli.d.ts +13 -0
  5. package/dist/cli.d.ts.map +1 -0
  6. package/dist/cli.js +160 -0
  7. package/dist/src/crossSectionUtils.d.ts +13 -0
  8. package/dist/src/crossSectionUtils.d.ts.map +1 -0
  9. package/dist/src/crossSectionUtils.js +25 -0
  10. package/dist/src/main.d.ts +16 -0
  11. package/dist/src/main.d.ts.map +1 -0
  12. package/dist/src/main.js +70 -0
  13. package/dist/src/makeCrossSection.d.ts +18 -0
  14. package/dist/src/makeCrossSection.d.ts.map +1 -0
  15. package/dist/src/makeCrossSection.js +42 -0
  16. package/dist/src/manifoldUtils.d.ts +9 -0
  17. package/dist/src/manifoldUtils.d.ts.map +1 -0
  18. package/dist/src/manifoldUtils.js +11 -0
  19. package/dist/src/params.d.ts +60 -0
  20. package/dist/src/params.d.ts.map +1 -0
  21. package/dist/src/params.js +44 -0
  22. package/dist/src/resvg.d.ts +10 -0
  23. package/dist/src/resvg.d.ts.map +1 -0
  24. package/dist/src/resvg.js +47 -0
  25. package/dist/src/threeMfExport.d.ts +9 -0
  26. package/dist/src/threeMfExport.d.ts.map +1 -0
  27. package/dist/src/threeMfExport.js +56 -0
  28. package/dist/src/tracing.d.ts +24 -0
  29. package/dist/src/tracing.d.ts.map +1 -0
  30. package/dist/src/tracing.js +71 -0
  31. package/dist/src/utils.d.ts +13 -0
  32. package/dist/src/utils.d.ts.map +1 -0
  33. package/dist/src/utils.js +53 -0
  34. package/images/cookiecad-logo-dark.svg +73 -0
  35. package/images/preview.png +0 -0
  36. package/package.json +56 -0
  37. package/src/crossSectionUtils.ts +30 -0
  38. package/src/main.ts +77 -0
  39. package/src/makeCrossSection.ts +57 -0
  40. package/src/manifoldUtils.ts +13 -0
  41. package/src/params.ts +70 -0
  42. package/src/resvg.ts +63 -0
  43. package/src/threeMfExport.ts +67 -0
  44. package/src/tracing.ts +94 -0
  45. package/src/types.d.ts +40 -0
  46. package/src/utils.ts +55 -0
package/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2024 CADit
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
package/README.md ADDED
@@ -0,0 +1,99 @@
1
+ # @cadit-app/image-extrude
2
+
3
+ Extrude 3D shapes from SVG or bitmap images. Supports both tracing (for raster images) and sampling (for SVGs).
4
+
5
+ ![Image Extrude Preview](images/preview.png)
6
+
7
+ ## Features
8
+
9
+ - **Trace mode**: Convert any bitmap image (PNG, JPG) to 3D by tracing edges (browser only)
10
+ - **Sample mode**: High-fidelity conversion of SVG files to 3D
11
+ - **Configurable size**: Set maximum width to control output dimensions
12
+ - **Despeckle**: Remove small artifacts during tracing
13
+ - **CLI support**: Generate GLB and 3MF files from command line (SVG sample mode)
14
+
15
+ > **Note:** Trace mode for bitmap images currently only works in the browser (CADit).
16
+ > The CLI only supports SVG files with sample mode.
17
+
18
+ ## Installation
19
+
20
+ ```bash
21
+ npm install @cadit-app/image-extrude
22
+ ```
23
+
24
+ ## Usage
25
+
26
+ ### As a CADit Script
27
+
28
+ Import this script in [CADit](https://cadit.app) by adding the GitHub repository URL.
29
+
30
+ ### CLI Usage
31
+
32
+ ```bash
33
+ # Generate GLB from default star shape
34
+ npx tsx cli.ts output.glb
35
+
36
+ # Generate from a specific image
37
+ npx tsx cli.ts output.glb --image=logo.svg --height=2 --maxWidth=50
38
+
39
+ # Generate 3MF
40
+ npx tsx cli.ts output.3mf --image=photo.png --mode=trace
41
+ ```
42
+
43
+ ### CLI Options
44
+
45
+ | Option | Description | Default |
46
+ |--------|-------------|---------|
47
+ | `--image=<path>` | Path to image file (SVG, PNG, JPG) | Built-in star |
48
+ | `--height=<mm>` | Extrusion height in mm | 1 |
49
+ | `--maxWidth=<mm>` | Maximum width in mm | 50 |
50
+ | `--mode=<trace\|sample>` | Processing mode | trace |
51
+ | `--despeckle=<size>` | Despeckle size for tracing | 2 |
52
+
53
+ ### Programmatic Usage
54
+
55
+ ```typescript
56
+ import imageExtrude from '@cadit-app/image-extrude';
57
+
58
+ // Use the defineParams API
59
+ const result = await imageExtrude.main({
60
+ mode: 'trace',
61
+ imageFile: {
62
+ dataUrl: 'data:image/png;base64,...',
63
+ fileType: 'image/png',
64
+ fileName: 'logo.png'
65
+ },
66
+ height: 2,
67
+ maxWidth: 50,
68
+ despeckleSize: 2
69
+ });
70
+ ```
71
+
72
+ ### Creating CrossSections for Embedding
73
+
74
+ ```typescript
75
+ import { makeCrossSection } from '@cadit-app/image-extrude';
76
+
77
+ const crossSection = await makeCrossSection({
78
+ imageFile: { dataUrl: '...', fileType: 'image/svg+xml' },
79
+ mode: 'sample',
80
+ maxWidth: 30
81
+ });
82
+
83
+ // Use in your own maker
84
+ const manifold = crossSection.extrude(5);
85
+ ```
86
+
87
+ ## Parameters
88
+
89
+ | Parameter | Type | Description |
90
+ |-----------|------|-------------|
91
+ | `mode` | `'trace' \| 'sample'` | Trace for bitmaps, Sample for SVGs |
92
+ | `imageFile` | `object` | Image data with dataUrl, fileType, fileName |
93
+ | `height` | `number` | Extrusion height in mm |
94
+ | `maxWidth` | `number` | Maximum width in mm |
95
+ | `despeckleSize` | `number` | Remove spots smaller than this (trace only) |
96
+
97
+ ## License
98
+
99
+ MIT
package/cadit.json ADDED
@@ -0,0 +1,20 @@
1
+ {
2
+ "name": "Image Extrude",
3
+ "description": "Extrude 3D shapes from SVG or bitmap images. Supports both tracing (for raster images) and sampling (for SVGs). Perfect for creating custom 3D prints from logos, icons, or artwork.",
4
+ "entryPoint": "src/main.ts",
5
+ "tags": ["image", "svg", "trace", "extrude", "3d-printing", "logo"],
6
+ "category": "Tools",
7
+ "license": {
8
+ "type": "MIT"
9
+ },
10
+ "author": {
11
+ "name": "CADit"
12
+ },
13
+ "images": [
14
+ {
15
+ "path": "images/preview.png",
16
+ "alt": "Image Extrude Preview",
17
+ "isPrimary": true
18
+ }
19
+ ]
20
+ }
package/dist/cli.d.ts ADDED
@@ -0,0 +1,13 @@
1
+ #!/usr/bin/env npx tsx
2
+ /**
3
+ * CLI for @cadit-app/image-extrude
4
+ *
5
+ * Usage:
6
+ * npx tsx cli.ts [output.glb|output.3mf] [options]
7
+ *
8
+ * Examples:
9
+ * npx tsx cli.ts output.glb
10
+ * npx tsx cli.ts output.3mf --image=logo.svg --height=2
11
+ */
12
+ export {};
13
+ //# sourceMappingURL=cli.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"cli.d.ts","sourceRoot":"","sources":["../cli.ts"],"names":[],"mappings":";AACA;;;;;;;;;GASG"}
package/dist/cli.js ADDED
@@ -0,0 +1,160 @@
1
+ #!/usr/bin/env npx tsx
2
+ /**
3
+ * CLI for @cadit-app/image-extrude
4
+ *
5
+ * Usage:
6
+ * npx tsx cli.ts [output.glb|output.3mf] [options]
7
+ *
8
+ * Examples:
9
+ * npx tsx cli.ts output.glb
10
+ * npx tsx cli.ts output.3mf --image=logo.svg --height=2
11
+ */
12
+ import { writeFileSync, readFileSync, existsSync } from 'fs';
13
+ import { resolve, extname, basename } from 'path';
14
+ import { parseArgs } from 'util';
15
+ const SUPPORTED_FORMATS = ['.glb', '.3mf'];
16
+ // Parse command line arguments
17
+ const { values, positionals } = parseArgs({
18
+ allowPositionals: true,
19
+ options: {
20
+ image: { type: 'string', short: 'i' },
21
+ height: { type: 'string', short: 'h' },
22
+ maxWidth: { type: 'string', short: 'w' },
23
+ mode: { type: 'string', short: 'm' },
24
+ despeckle: { type: 'string', short: 'd' },
25
+ help: { type: 'boolean' },
26
+ },
27
+ });
28
+ if (values.help || positionals.length === 0) {
29
+ console.log(`
30
+ @cadit-app/image-extrude CLI
31
+
32
+ Usage: npx tsx cli.ts <output.[glb|3mf]> [options]
33
+
34
+ Options:
35
+ -i, --image <path> Path to image file (SVG, PNG, JPG)
36
+ -h, --height <mm> Extrusion height in mm (default: 1)
37
+ -w, --maxWidth <mm> Maximum width in mm (default: 50)
38
+ -m, --mode <trace|sample> Processing mode (default: trace)
39
+ -d, --despeckle <size> Despeckle size for tracing (default: 2)
40
+ --help Show this help
41
+
42
+ Examples:
43
+ npx tsx cli.ts output.glb
44
+ npx tsx cli.ts output.glb --image logo.svg --height 2
45
+ npx tsx cli.ts output.3mf --image photo.png --mode trace
46
+ `);
47
+ process.exit(0);
48
+ }
49
+ const outputFile = positionals[0];
50
+ const ext = extname(outputFile).toLowerCase();
51
+ if (!SUPPORTED_FORMATS.includes(ext)) {
52
+ console.error(`Error: Output file must have one of these extensions: ${SUPPORTED_FORMATS.join(', ')}`);
53
+ console.error(`Got: ${ext}`);
54
+ process.exit(1);
55
+ }
56
+ async function main() {
57
+ console.log('Initializing manifold...');
58
+ // Initialize manifold-3d
59
+ const manifold = await import('@cadit-app/manifold-3d');
60
+ await manifold.default();
61
+ // Now import the maker
62
+ const { default: imageExtrudeMaker } = await import('./src/main');
63
+ const { imageExtrudeParamsSchema } = await import('./src/params');
64
+ console.log('Generating image extrusion...');
65
+ // Build params from defaults and CLI options
66
+ const defaultParams = {};
67
+ for (const [key, param] of Object.entries(imageExtrudeParamsSchema)) {
68
+ defaultParams[key] = param.default;
69
+ }
70
+ // Load default image from images folder if no image specified
71
+ const defaultImagePath = resolve(import.meta.dirname, 'images', 'cookiecad-logo-dark.svg');
72
+ const imagePath = values.image && existsSync(values.image) ? values.image : defaultImagePath;
73
+ // Override with CLI options
74
+ if (values.height) {
75
+ defaultParams.height = parseFloat(values.height);
76
+ }
77
+ if (values.maxWidth) {
78
+ defaultParams.maxWidth = parseFloat(values.maxWidth);
79
+ }
80
+ // Default to 'sample' mode for CLI (trace requires additional WASM setup for non-SVG)
81
+ if (values.mode && (values.mode === 'trace' || values.mode === 'sample')) {
82
+ defaultParams.mode = values.mode;
83
+ }
84
+ else if (!values.mode && imagePath.endsWith('.svg')) {
85
+ defaultParams.mode = 'sample'; // Default to sample for SVGs in CLI
86
+ }
87
+ if (values.despeckle) {
88
+ defaultParams.despeckleSize = parseFloat(values.despeckle);
89
+ }
90
+ if (existsSync(imagePath)) {
91
+ const imageData = readFileSync(imagePath);
92
+ const base64 = imageData.toString('base64');
93
+ const imageExt = extname(imagePath).toLowerCase();
94
+ const mimeType = imageExt === '.svg' ? 'image/svg+xml' :
95
+ imageExt === '.png' ? 'image/png' :
96
+ imageExt === '.jpg' || imageExt === '.jpeg' ? 'image/jpeg' :
97
+ 'application/octet-stream';
98
+ defaultParams.imageFile = {
99
+ dataUrl: `data:${mimeType};base64,${base64}`,
100
+ fileType: mimeType,
101
+ fileName: basename(imagePath)
102
+ };
103
+ }
104
+ console.log('Parameters:', {
105
+ mode: defaultParams.mode,
106
+ height: defaultParams.height,
107
+ maxWidth: defaultParams.maxWidth,
108
+ despeckleSize: defaultParams.despeckleSize,
109
+ hasImage: !!defaultParams.imageFile?.dataUrl
110
+ });
111
+ // Generate the model
112
+ const result = await imageExtrudeMaker(defaultParams);
113
+ if (ext === '.glb') {
114
+ // Export as GLB
115
+ const mesh = result.getMesh();
116
+ const { Document, NodeIO } = await import('@gltf-transform/core');
117
+ const document = new Document();
118
+ const buffer = document.createBuffer();
119
+ const scene = document.createScene();
120
+ const node = document.createNode();
121
+ scene.addChild(node);
122
+ // Create mesh
123
+ const primitive = document.createPrimitive();
124
+ // Position accessor
125
+ const positions = new Float32Array(mesh.vertProperties);
126
+ const positionAccessor = document.createAccessor()
127
+ .setType('VEC3')
128
+ .setBuffer(buffer)
129
+ .setArray(positions);
130
+ primitive.setAttribute('POSITION', positionAccessor);
131
+ // Index accessor
132
+ const indices = new Uint32Array(mesh.triVerts);
133
+ const indexAccessor = document.createAccessor()
134
+ .setType('SCALAR')
135
+ .setBuffer(buffer)
136
+ .setArray(indices);
137
+ primitive.setIndices(indexAccessor);
138
+ // Material
139
+ const material = document.createMaterial()
140
+ .setBaseColorFactor([0.2, 0.8, 0.6, 1.0]);
141
+ primitive.setMaterial(material);
142
+ const gltfMesh = document.createMesh().addPrimitive(primitive);
143
+ node.setMesh(gltfMesh);
144
+ const io = new NodeIO();
145
+ const glb = await io.writeBinary(document);
146
+ writeFileSync(resolve(outputFile), glb);
147
+ console.log(`Wrote ${outputFile}`);
148
+ }
149
+ else if (ext === '.3mf') {
150
+ // Export as 3MF
151
+ const { create3mfArrayBuffer } = await import('./src/threeMfExport');
152
+ const buffer = await create3mfArrayBuffer([result]);
153
+ writeFileSync(resolve(outputFile), Buffer.from(buffer));
154
+ console.log(`Wrote ${outputFile}`);
155
+ }
156
+ }
157
+ main().catch(err => {
158
+ console.error('Error:', err);
159
+ process.exit(1);
160
+ });
@@ -0,0 +1,13 @@
1
+ /**
2
+ * CrossSection utility functions
3
+ */
4
+ import { CrossSection } from '@cadit-app/manifold-3d/manifoldCAD';
5
+ /**
6
+ * Centers a CrossSection at the origin based on its bounding box
7
+ */
8
+ export declare function centerCrossSection(crossSection: CrossSection): CrossSection;
9
+ /**
10
+ * Scales a CrossSection to fit within a maximum size while maintaining aspect ratio
11
+ */
12
+ export declare function scaleToMaxSize(crossSection: CrossSection, maxSize: number): CrossSection;
13
+ //# sourceMappingURL=crossSectionUtils.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"crossSectionUtils.d.ts","sourceRoot":"","sources":["../../src/crossSectionUtils.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,EAAE,YAAY,EAAE,MAAM,oCAAoC,CAAC;AAElE;;GAEG;AACH,wBAAgB,kBAAkB,CAAC,YAAY,EAAE,YAAY,GAAG,YAAY,CAK3E;AAED;;GAEG;AACH,wBAAgB,cAAc,CAAC,YAAY,EAAE,YAAY,EAAE,OAAO,EAAE,MAAM,GAAG,YAAY,CAUxF"}
@@ -0,0 +1,25 @@
1
+ /**
2
+ * CrossSection utility functions
3
+ */
4
+ /**
5
+ * Centers a CrossSection at the origin based on its bounding box
6
+ */
7
+ export function centerCrossSection(crossSection) {
8
+ const bounds = crossSection.bounds();
9
+ const centerX = (bounds.min[0] + bounds.max[0]) / 2;
10
+ const centerY = (bounds.min[1] + bounds.max[1]) / 2;
11
+ return crossSection.translate([-centerX, -centerY]);
12
+ }
13
+ /**
14
+ * Scales a CrossSection to fit within a maximum size while maintaining aspect ratio
15
+ */
16
+ export function scaleToMaxSize(crossSection, maxSize) {
17
+ const bounds = crossSection.bounds();
18
+ const width = bounds.max[0] - bounds.min[0];
19
+ const height = bounds.max[1] - bounds.min[1];
20
+ const maxDim = Math.max(width, height);
21
+ if (maxDim <= 0)
22
+ return crossSection;
23
+ const scale = maxSize / maxDim;
24
+ return crossSection.scale([scale, scale]);
25
+ }
@@ -0,0 +1,16 @@
1
+ /**
2
+ * @cadit-app/image-extrude
3
+ *
4
+ * Extrude 3D shapes from SVG or bitmap images.
5
+ * Uses the defineParams API from @cadit-app/script-params.
6
+ */
7
+ import type { Manifold } from '@cadit-app/manifold-3d/manifoldCAD';
8
+ export { sampleSvg, traceImage } from './tracing';
9
+ export { renderSvgToBitmapDataUrl } from './resvg';
10
+ export { makeCrossSection } from './makeCrossSection';
11
+ /**
12
+ * Main entry point using defineParams
13
+ */
14
+ declare const _default: import("@cadit-app/script-params").ScriptModule<any, Promise<Manifold>>;
15
+ export default _default;
16
+ //# sourceMappingURL=main.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"main.d.ts","sourceRoot":"","sources":["../../src/main.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAGH,OAAO,KAAK,EAAE,QAAQ,EAAgB,MAAM,oCAAoC,CAAC;AAQjF,OAAO,EAAE,SAAS,EAAE,UAAU,EAAE,MAAM,WAAW,CAAC;AAClD,OAAO,EAAE,wBAAwB,EAAE,MAAM,SAAS,CAAC;AACnD,OAAO,EAAE,gBAAgB,EAAE,MAAM,oBAAoB,CAAC;AAEtD;;GAEG;;AACH,wBAqDG"}
@@ -0,0 +1,70 @@
1
+ /**
2
+ * @cadit-app/image-extrude
3
+ *
4
+ * Extrude 3D shapes from SVG or bitmap images.
5
+ * Uses the defineParams API from @cadit-app/script-params.
6
+ */
7
+ import { defineParams } from '@cadit-app/script-params';
8
+ import { imageExtrudeParamsSchema } from './params';
9
+ import { sampleSvg, traceImage } from './tracing';
10
+ import { renderSvgToBitmapDataUrl } from './resvg';
11
+ import { fetchImageAsDataUrl } from './utils';
12
+ import { createEmptyManifold } from './manifoldUtils';
13
+ // Re-export for external use
14
+ export { sampleSvg, traceImage } from './tracing';
15
+ export { renderSvgToBitmapDataUrl } from './resvg';
16
+ export { makeCrossSection } from './makeCrossSection';
17
+ /**
18
+ * Main entry point using defineParams
19
+ */
20
+ export default defineParams({
21
+ params: imageExtrudeParamsSchema,
22
+ main: async (params) => {
23
+ const typedParams = params;
24
+ let { mode, height } = typedParams;
25
+ let imageFile = typedParams.imageFile;
26
+ // If imageFile has imageUrl but not dataUrl, fetch and convert to dataUrl
27
+ if (imageFile && !imageFile.dataUrl && imageFile.imageUrl) {
28
+ try {
29
+ imageFile = {
30
+ ...imageFile,
31
+ dataUrl: await fetchImageAsDataUrl(imageFile.imageUrl)
32
+ };
33
+ }
34
+ catch (err) {
35
+ console.warn('Failed to fetch imageUrl:', err);
36
+ return createEmptyManifold();
37
+ }
38
+ }
39
+ if (!imageFile || !imageFile.dataUrl) {
40
+ console.warn('No valid image file provided.');
41
+ return createEmptyManifold();
42
+ }
43
+ // Adjust mode if sample is selected for non-SVG
44
+ if (mode === 'sample' && !imageFile.fileType?.includes('svg')) {
45
+ console.warn('Sample mode selected for non-SVG file. Defaulting to Trace mode.');
46
+ mode = 'trace';
47
+ }
48
+ let crossSection;
49
+ try {
50
+ if (mode === 'trace') {
51
+ // if svg, render svg to bitmap and then trace
52
+ const isSvg = imageFile.fileType?.includes('svg');
53
+ const dataUrl = isSvg ? await renderSvgToBitmapDataUrl(imageFile.dataUrl) : imageFile.dataUrl;
54
+ crossSection = await traceImage(dataUrl, {
55
+ maxWidth: typedParams.maxWidth,
56
+ despeckleSize: typedParams.despeckleSize
57
+ });
58
+ }
59
+ else {
60
+ // mode is 'sample', and fileType is guaranteed to be svg+xml
61
+ crossSection = await sampleSvg(imageFile.dataUrl, typedParams.maxWidth);
62
+ }
63
+ }
64
+ catch (error) {
65
+ console.error(`Error during image processing (mode: ${mode}):`, error);
66
+ return createEmptyManifold();
67
+ }
68
+ return crossSection.extrude(height);
69
+ },
70
+ });
@@ -0,0 +1,18 @@
1
+ /**
2
+ * Create a CrossSection from image parameters
3
+ * Exported for external use (e.g., embedding in other makers)
4
+ */
5
+ import type { CrossSection } from '@cadit-app/manifold-3d/manifoldCAD';
6
+ import { ImageExtrudeParams } from './params';
7
+ export type MakeCrossSectionOptions = {
8
+ imageFile: ImageExtrudeParams['imageFile'];
9
+ mode: 'trace' | 'sample';
10
+ maxWidth?: number;
11
+ despeckleSize?: number;
12
+ };
13
+ /**
14
+ * Creates a CrossSection from image data
15
+ * This is the main function for embedding in other makers
16
+ */
17
+ export declare function makeCrossSection(options: MakeCrossSectionOptions): Promise<CrossSection>;
18
+ //# sourceMappingURL=makeCrossSection.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"makeCrossSection.d.ts","sourceRoot":"","sources":["../../src/makeCrossSection.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,oCAAoC,CAAC;AACvE,OAAO,EAAE,kBAAkB,EAAE,MAAM,UAAU,CAAC;AAK9C,MAAM,MAAM,uBAAuB,GAAG;IACpC,SAAS,EAAE,kBAAkB,CAAC,WAAW,CAAC,CAAC;IAC3C,IAAI,EAAE,OAAO,GAAG,QAAQ,CAAC;IACzB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,aAAa,CAAC,EAAE,MAAM,CAAC;CACxB,CAAC;AAEF;;;GAGG;AACH,wBAAsB,gBAAgB,CAAC,OAAO,EAAE,uBAAuB,GAAG,OAAO,CAAC,YAAY,CAAC,CAkC9F"}
@@ -0,0 +1,42 @@
1
+ /**
2
+ * Create a CrossSection from image parameters
3
+ * Exported for external use (e.g., embedding in other makers)
4
+ */
5
+ import { sampleSvg, traceImage } from './tracing';
6
+ import { renderSvgToBitmapDataUrl } from './resvg';
7
+ import { fetchImageAsDataUrl } from './utils';
8
+ /**
9
+ * Creates a CrossSection from image data
10
+ * This is the main function for embedding in other makers
11
+ */
12
+ export async function makeCrossSection(options) {
13
+ let { imageFile, mode, maxWidth, despeckleSize } = options;
14
+ // If imageFile has imageUrl but not dataUrl, fetch and convert
15
+ if (imageFile && !imageFile.dataUrl && imageFile.imageUrl) {
16
+ imageFile = {
17
+ ...imageFile,
18
+ dataUrl: await fetchImageAsDataUrl(imageFile.imageUrl)
19
+ };
20
+ }
21
+ if (!imageFile?.dataUrl) {
22
+ throw new Error('No valid image file provided');
23
+ }
24
+ // Adjust mode if sample is selected for non-SVG
25
+ if (mode === 'sample' && !imageFile.fileType?.includes('svg')) {
26
+ console.warn('Sample mode selected for non-SVG file. Defaulting to Trace mode.');
27
+ mode = 'trace';
28
+ }
29
+ if (mode === 'trace') {
30
+ // if svg, render svg to bitmap and then trace
31
+ const isSvg = imageFile.fileType?.includes('svg');
32
+ const dataUrl = isSvg ? await renderSvgToBitmapDataUrl(imageFile.dataUrl) : imageFile.dataUrl;
33
+ return traceImage(dataUrl, {
34
+ maxWidth,
35
+ despeckleSize
36
+ });
37
+ }
38
+ else {
39
+ // mode is 'sample', and fileType is guaranteed to be svg+xml
40
+ return sampleSvg(imageFile.dataUrl, maxWidth);
41
+ }
42
+ }
@@ -0,0 +1,9 @@
1
+ /**
2
+ * Manifold utility functions
3
+ */
4
+ import { Manifold } from '@cadit-app/manifold-3d/manifoldCAD';
5
+ /**
6
+ * Creates an empty manifold (a very small cube that will be invisible)
7
+ */
8
+ export declare function createEmptyManifold(): Manifold;
9
+ //# sourceMappingURL=manifoldUtils.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"manifoldUtils.d.ts","sourceRoot":"","sources":["../../src/manifoldUtils.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,EAAE,QAAQ,EAAgB,MAAM,oCAAoC,CAAC;AAE5E;;GAEG;AACH,wBAAgB,mBAAmB,IAAI,QAAQ,CAG9C"}
@@ -0,0 +1,11 @@
1
+ /**
2
+ * Manifold utility functions
3
+ */
4
+ import { CrossSection } from '@cadit-app/manifold-3d/manifoldCAD';
5
+ /**
6
+ * Creates an empty manifold (a very small cube that will be invisible)
7
+ */
8
+ export function createEmptyManifold() {
9
+ // Create a tiny box that's essentially invisible
10
+ return CrossSection.square([0.001, 0.001], true).extrude(0.001);
11
+ }
@@ -0,0 +1,60 @@
1
+ /**
2
+ * Parameter schema for the Image Extrude generator.
3
+ */
4
+ /**
5
+ * Value type for image parameters.
6
+ * Matches the ImageFileValue type from @cadit-app/script-params.
7
+ * TODO: Import from script-params once version with ImageFileValue is published.
8
+ */
9
+ export interface ImageFileValue {
10
+ /** Remote URL to fetch the image from (e.g., HTTP URL or relative path). */
11
+ imageUrl?: string;
12
+ /** Base64-encoded data URL of the image content. */
13
+ dataUrl?: string;
14
+ /** MIME type of the image (e.g., 'image/svg+xml', 'image/png'). */
15
+ fileType?: string;
16
+ /** Original filename of the image. */
17
+ fileName?: string;
18
+ }
19
+ export declare const imageExtrudeParamsSchema: {
20
+ mode: {
21
+ type: "choice";
22
+ label: string;
23
+ options: {
24
+ value: string;
25
+ label: string;
26
+ }[];
27
+ default: string;
28
+ };
29
+ imageFile: {
30
+ type: "image";
31
+ label: string;
32
+ default: ImageFileValue;
33
+ };
34
+ height: {
35
+ type: "number";
36
+ label: string;
37
+ default: number;
38
+ min: number;
39
+ };
40
+ maxWidth: {
41
+ type: "number";
42
+ label: string;
43
+ default: number;
44
+ min: number;
45
+ };
46
+ despeckleSize: {
47
+ type: "number";
48
+ label: string;
49
+ default: number;
50
+ min: number;
51
+ };
52
+ };
53
+ export type ImageExtrudeParams = {
54
+ mode: 'trace' | 'sample';
55
+ imageFile: ImageFileValue;
56
+ height: number;
57
+ maxWidth: number;
58
+ despeckleSize: number;
59
+ };
60
+ //# sourceMappingURL=params.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"params.d.ts","sourceRoot":"","sources":["../../src/params.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH;;;;GAIG;AACH,MAAM,WAAW,cAAc;IAC7B,4EAA4E;IAC5E,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,oDAAoD;IACpD,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,mEAAmE;IACnE,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,sCAAsC;IACtC,QAAQ,CAAC,EAAE,MAAM,CAAC;CACnB;AAKD,eAAO,MAAM,wBAAwB;;;;;;;;;;;;;iBAkB5B,cAAc;;;;;;;;;;;;;;;;;;;;CAoBtB,CAAC;AAEF,MAAM,MAAM,kBAAkB,GAAG;IAC/B,IAAI,EAAE,OAAO,GAAG,QAAQ,CAAC;IACzB,SAAS,EAAE,cAAc,CAAC;IAC1B,MAAM,EAAE,MAAM,CAAC;IACf,QAAQ,EAAE,MAAM,CAAC;IACjB,aAAa,EAAE,MAAM,CAAC;CACvB,CAAC"}
@@ -0,0 +1,44 @@
1
+ /**
2
+ * Parameter schema for the Image Extrude generator.
3
+ */
4
+ // Default SVG - a simple star shape
5
+ const defaultSvgDataUrl = 'data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCAxMDAgMTAwIj48cG9seWdvbiBwb2ludHM9IjUwLDUgNjEsMzkgOTcsMzkgNjgsMjIgNzksOTUgNTAsNzAgMjEsOTUgMzIsNjIgMywzOSAzOSwzOSIgZmlsbD0iYmxhY2siLz48L3N2Zz4=';
6
+ export const imageExtrudeParamsSchema = {
7
+ mode: {
8
+ type: 'choice',
9
+ label: 'Mode',
10
+ options: [
11
+ { value: 'trace', label: 'Trace' },
12
+ { value: 'sample', label: 'Sample (SVG only)' },
13
+ ],
14
+ default: 'trace',
15
+ },
16
+ imageFile: {
17
+ type: 'image',
18
+ label: 'Image File',
19
+ default: {
20
+ imageUrl: '',
21
+ dataUrl: defaultSvgDataUrl,
22
+ fileType: 'image/svg+xml',
23
+ fileName: 'star.svg'
24
+ },
25
+ },
26
+ height: {
27
+ type: 'number',
28
+ label: 'Extrusion Height (mm)',
29
+ default: 1,
30
+ min: 0.1,
31
+ },
32
+ maxWidth: {
33
+ type: 'number',
34
+ label: 'Maximum Width (mm)',
35
+ default: 50,
36
+ min: 0.1,
37
+ },
38
+ despeckleSize: {
39
+ type: 'number',
40
+ label: 'Despeckle Size (Tracing only)',
41
+ default: 2,
42
+ min: 0.1,
43
+ },
44
+ };
@@ -0,0 +1,10 @@
1
+ /**
2
+ * SVG to bitmap rendering using resvg-wasm
3
+ */
4
+ /**
5
+ * Renders an SVG Data URL to a PNG Data URL using resvg-wasm.
6
+ */
7
+ export declare const renderSvgToBitmapDataUrl: (svgDataUrl: string, options?: {
8
+ maxWidth?: number;
9
+ }) => Promise<string>;
10
+ //# sourceMappingURL=resvg.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"resvg.d.ts","sourceRoot":"","sources":["../../src/resvg.ts"],"names":[],"mappings":"AAAA;;GAEG;AA+BH;;GAEG;AACH,eAAO,MAAM,wBAAwB,GACnC,YAAY,MAAM,EAClB,UAAU;IAAE,QAAQ,CAAC,EAAE,MAAM,CAAA;CAAE,KAC9B,OAAO,CAAC,MAAM,CAuBhB,CAAC"}