@jscad/svg-deserializer 3.0.0-alpha.0 → 3.0.2-alpha.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 +17 -0
- package/LICENSE +1 -1
- package/dist/jscad-svg-deserializer.es.js +3 -3
- package/dist/jscad-svg-deserializer.min.js +3 -3
- package/package.json +5 -4
- package/rollup.config.js +1 -1
- package/src/index.js +3 -0
- package/src/shapesMapGeometry.js +41 -20
- package/src/shapesMapJscad.js +8 -8
- package/tests/instantiate.test.js +10 -18
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@jscad/svg-deserializer",
|
|
3
|
-
"version": "3.0.
|
|
3
|
+
"version": "3.0.2-alpha.0",
|
|
4
4
|
"description": "SVG Deserializer for JSCAD",
|
|
5
5
|
"homepage": "https://openjscad.xyz/",
|
|
6
6
|
"repository": "https://github.com/jscad/OpenJSCAD.org",
|
|
@@ -37,8 +37,9 @@
|
|
|
37
37
|
],
|
|
38
38
|
"license": "MIT",
|
|
39
39
|
"dependencies": {
|
|
40
|
-
"@jscad/array-utils": "3.0.
|
|
41
|
-
"@jscad/
|
|
40
|
+
"@jscad/array-utils": "3.0.1-alpha.0",
|
|
41
|
+
"@jscad/io-utils": "3.0.2-alpha.0",
|
|
42
|
+
"@jscad/modeling": "3.0.2-alpha.0",
|
|
42
43
|
"saxes": "6.0.0"
|
|
43
44
|
},
|
|
44
45
|
"devDependencies": {
|
|
@@ -51,5 +52,5 @@
|
|
|
51
52
|
"rollup-plugin-banner": "^0.2.1",
|
|
52
53
|
"rollup-plugin-version-injector": "^1.3.3"
|
|
53
54
|
},
|
|
54
|
-
"gitHead": "
|
|
55
|
+
"gitHead": "ac80d1a7cb0a8efb21aff9193d4a8bccb6e31f1c"
|
|
55
56
|
}
|
package/rollup.config.js
CHANGED
|
@@ -24,6 +24,6 @@ export default {
|
|
|
24
24
|
nodeResolve(),
|
|
25
25
|
banner('<%= pkg.description %>\n@module <%= pkg.name %>\n@version <%= pkg.version %>\n@license <%= pkg.license %>'),
|
|
26
26
|
versionInjector({ injectInComments: { fileRegexp: /\.(html)$/ }, logLevel: 'warn' }),
|
|
27
|
-
terser({ compress: { module: true }, mangle: false, format: { comments: 'some'} })
|
|
27
|
+
terser({ compress: { module: true }, mangle: false, format: { comments: 'some' } })
|
|
28
28
|
]
|
|
29
29
|
}
|
package/src/index.js
CHANGED
|
@@ -2,6 +2,7 @@ import saxes from 'saxes'
|
|
|
2
2
|
|
|
3
3
|
import { colorize, mirrorX, mirrorY, rotateZ, translate, scale } from '@jscad/modeling'
|
|
4
4
|
import { toArray } from '@jscad/array-utils'
|
|
5
|
+
import { ensureString } from '@jscad/io-utils'
|
|
5
6
|
|
|
6
7
|
import { pxPmm } from './constants.js'
|
|
7
8
|
import { cagLengthX, cagLengthY, svgColorForTarget } from './helpers.js'
|
|
@@ -47,6 +48,8 @@ const deserialize = (options, input) => {
|
|
|
47
48
|
version
|
|
48
49
|
}
|
|
49
50
|
options = Object.assign({}, defaults, options)
|
|
51
|
+
|
|
52
|
+
input = ensureString(input)
|
|
50
53
|
return options.output === 'script' ? translateScript(input, options) : instantiate(input, options)
|
|
51
54
|
}
|
|
52
55
|
|
package/src/shapesMapGeometry.js
CHANGED
|
@@ -133,15 +133,22 @@ export const shapesMapGeometry = (obj, objectify, params) => {
|
|
|
133
133
|
const listofpaths = expandPath(obj, svgUnitsPmm, svgUnitsX, svgUnitsY, svgUnitsV, svgGroups, segments, pathSelfClosed)
|
|
134
134
|
// order is important
|
|
135
135
|
const listofentries = Object.entries(listofpaths).sort((a, b) => a[0].localeCompare(b[0]))
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
136
|
+
if (target === 'geom2') {
|
|
137
|
+
// concatenate all sides to a single geom2
|
|
138
|
+
const outlines = []
|
|
139
|
+
listofentries.forEach((entry) => {
|
|
140
|
+
const path = entry[1]
|
|
141
|
+
// discard unclosed paths
|
|
142
|
+
if (path.isClosed) {
|
|
143
|
+
const points = path2.toPoints(path)
|
|
144
|
+
outlines.push(points)
|
|
145
|
+
}
|
|
146
|
+
})
|
|
147
|
+
if (outlines.length === 0) return []
|
|
148
|
+
return geom2.create(outlines)
|
|
149
|
+
} else {
|
|
150
|
+
return listofentries.map((entry) => entry[1])
|
|
151
|
+
}
|
|
145
152
|
}
|
|
146
153
|
}
|
|
147
154
|
|
|
@@ -153,6 +160,18 @@ const appendPoints = (points, geometry) => {
|
|
|
153
160
|
return path2.fromPoints({ }, points)
|
|
154
161
|
}
|
|
155
162
|
|
|
163
|
+
/*
|
|
164
|
+
* Expands the given SVG path object into a set of path segments.
|
|
165
|
+
* @param {object} obj - SVG path object to expand
|
|
166
|
+
* @param {number} svgUnitsPmm - SVG units per millimeter
|
|
167
|
+
* @param {number} svgUnitsX - X-axis SVG units
|
|
168
|
+
* @param {number} svgUnitsY - Y-axis SVG units
|
|
169
|
+
* @param {number} svgUnitsV - SVG units value
|
|
170
|
+
* @param {object} svgGroups - SVG groups object
|
|
171
|
+
* @param {number} segments - number of segments per 360 rotation
|
|
172
|
+
* @param {boolean} pathSelfClosed - Whether the path is self-closed
|
|
173
|
+
* @returns {object} a object containing the named paths
|
|
174
|
+
*/
|
|
156
175
|
const expandPath = (obj, svgUnitsPmm, svgUnitsX, svgUnitsY, svgUnitsV, svgGroups, segments, pathSelfClosed) => {
|
|
157
176
|
const paths = {}
|
|
158
177
|
const on = 'path'
|
|
@@ -185,8 +204,9 @@ const expandPath = (obj, svgUnitsPmm, svgUnitsX, svgUnitsY, svgUnitsV, svgGroups
|
|
|
185
204
|
pc = false
|
|
186
205
|
}
|
|
187
206
|
const ensurePath = () => {
|
|
188
|
-
if (!paths[pathName])
|
|
189
|
-
|
|
207
|
+
if (!paths[pathName]) {
|
|
208
|
+
paths[pathName] = path2.fromPoints({}, [])
|
|
209
|
+
}
|
|
190
210
|
}
|
|
191
211
|
for (let j = 0; j < obj.commands.length; j++) {
|
|
192
212
|
const co = obj.commands[j]
|
|
@@ -328,8 +348,8 @@ const expandPath = (obj, svgUnitsPmm, svgUnitsX, svgUnitsY, svgUnitsV, svgGroups
|
|
|
328
348
|
qy = cy + parseFloat(pts[i++])
|
|
329
349
|
cx = cx + parseFloat(pts[i++])
|
|
330
350
|
cy = cy + parseFloat(pts[i++])
|
|
331
|
-
const q1 = [p0[0] + (2/3) * (qx - p0[0]), p0[1] + (2/3) * (qy - p0[1])]
|
|
332
|
-
const q2 = [q1[0] + (1/3) * (cx - p0[0]), q1[1] + (1/3) * (cy - p0[1])]
|
|
351
|
+
const q1 = [p0[0] + (2 / 3) * (qx - p0[0]), p0[1] + (2 / 3) * (qy - p0[1])]
|
|
352
|
+
const q2 = [q1[0] + (1 / 3) * (cx - p0[0]), q1[1] + (1 / 3) * (cy - p0[1])]
|
|
333
353
|
ensurePath()
|
|
334
354
|
paths[pathName] = path2.appendBezier({
|
|
335
355
|
segments,
|
|
@@ -351,8 +371,8 @@ const expandPath = (obj, svgUnitsPmm, svgUnitsX, svgUnitsY, svgUnitsV, svgGroups
|
|
|
351
371
|
qy = parseFloat(pts[i++])
|
|
352
372
|
cx = parseFloat(pts[i++])
|
|
353
373
|
cy = parseFloat(pts[i++])
|
|
354
|
-
const q1 = [p0[0] + (2/3) * (qx - p0[0]), p0[1] + (2/3) * (qy - p0[1])]
|
|
355
|
-
const q2 = [q1[0] + (1/3) * (cx - p0[0]), q1[1] + (1/3) * (cy - p0[1])]
|
|
374
|
+
const q1 = [p0[0] + (2 / 3) * (qx - p0[0]), p0[1] + (2 / 3) * (qy - p0[1])]
|
|
375
|
+
const q2 = [q1[0] + (1 / 3) * (cx - p0[0]), q1[1] + (1 / 3) * (cy - p0[1])]
|
|
356
376
|
ensurePath()
|
|
357
377
|
paths[pathName] = path2.appendBezier({
|
|
358
378
|
segments,
|
|
@@ -372,8 +392,8 @@ const expandPath = (obj, svgUnitsPmm, svgUnitsX, svgUnitsY, svgUnitsV, svgGroups
|
|
|
372
392
|
const p0 = [cx, cy] // previous point
|
|
373
393
|
cx = cx + parseFloat(pts[i++])
|
|
374
394
|
cy = cy + parseFloat(pts[i++])
|
|
375
|
-
const q1 = [p0[0] + (2/3) * (qx - p0[0]), p0[1] + (2/3) * (qy - p0[1])]
|
|
376
|
-
const q2 = [q1[0] + (1/3) * (cx - p0[0]), q1[1] + (1/3) * (cy - p0[1])]
|
|
395
|
+
const q1 = [p0[0] + (2 / 3) * (qx - p0[0]), p0[1] + (2 / 3) * (qy - p0[1])]
|
|
396
|
+
const q2 = [q1[0] + (1 / 3) * (cx - p0[0]), q1[1] + (1 / 3) * (cy - p0[1])]
|
|
377
397
|
ensurePath()
|
|
378
398
|
paths[pathName] = path2.appendBezier({
|
|
379
399
|
segments,
|
|
@@ -393,8 +413,8 @@ const expandPath = (obj, svgUnitsPmm, svgUnitsX, svgUnitsY, svgUnitsV, svgGroups
|
|
|
393
413
|
const p0 = [cx, cy] // previous point
|
|
394
414
|
cx = parseFloat(pts[i++])
|
|
395
415
|
cy = parseFloat(pts[i++])
|
|
396
|
-
const q1 = [p0[0] + (2/3) * (qx - p0[0]), p0[1] + (2/3) * (qy - p0[1])]
|
|
397
|
-
const q2 = [q1[0] + (1/3) * (cx - p0[0]), q1[1] + (1/3) * (cy - p0[1])]
|
|
416
|
+
const q1 = [p0[0] + (2 / 3) * (qx - p0[0]), p0[1] + (2 / 3) * (qy - p0[1])]
|
|
417
|
+
const q2 = [q1[0] + (1 / 3) * (cx - p0[0]), q1[1] + (1 / 3) * (cy - p0[1])]
|
|
398
418
|
ensurePath()
|
|
399
419
|
paths[pathName] = path2.appendBezier({
|
|
400
420
|
segments,
|
|
@@ -419,7 +439,8 @@ const expandPath = (obj, svgUnitsPmm, svgUnitsX, svgUnitsY, svgUnitsV, svgGroups
|
|
|
419
439
|
cy = cy + parseFloat(pts[i++])
|
|
420
440
|
ensurePath()
|
|
421
441
|
paths[pathName] = path2.appendBezier({
|
|
422
|
-
segments,
|
|
442
|
+
segments,
|
|
443
|
+
controlPoints: [
|
|
423
444
|
svg2cag([x1, y1], svgUnitsPmm),
|
|
424
445
|
svg2cag([bx, by], svgUnitsPmm),
|
|
425
446
|
svg2cag([cx, cy], svgUnitsPmm)
|
package/src/shapesMapJscad.js
CHANGED
|
@@ -258,8 +258,8 @@ const path = (obj, svgUnitsPmm, svgUnitsX, svgUnitsY, svgUnitsV, params, svgGrou
|
|
|
258
258
|
qy = cy + parseFloat(pts.shift())
|
|
259
259
|
cx = cx + parseFloat(pts.shift()) // end point
|
|
260
260
|
cy = cy + parseFloat(pts.shift())
|
|
261
|
-
const q1 = [p0[0] + (2/3) * (qx - p0[0]), p0[1] + (2/3) * (qy - p0[1])]
|
|
262
|
-
const q2 = [q1[0] + (1/3) * (cx - p0[0]), q1[1] + (1/3) * (cy - p0[1])]
|
|
261
|
+
const q1 = [p0[0] + (2 / 3) * (qx - p0[0]), p0[1] + (2 / 3) * (qy - p0[1])]
|
|
262
|
+
const q2 = [q1[0] + (1 / 3) * (cx - p0[0]), q1[1] + (1 / 3) * (cy - p0[1])]
|
|
263
263
|
tmpCode += `${indent}${pathName} = path2.appendBezier({segments: ${segments}, controlPoints: [[${svg2cag(q1, svgUnitsPmm)}], [${svg2cag(q2, svgUnitsPmm)}], [${svg2cag([cx, cy], svgUnitsPmm)}]]}, ${pathName})\n`
|
|
264
264
|
const rf = reflect(qx, qy, cx, cy)
|
|
265
265
|
qx = rf[0]
|
|
@@ -273,8 +273,8 @@ const path = (obj, svgUnitsPmm, svgUnitsX, svgUnitsY, svgUnitsV, params, svgGrou
|
|
|
273
273
|
qy = parseFloat(pts.shift())
|
|
274
274
|
cx = parseFloat(pts.shift()) // end point
|
|
275
275
|
cy = parseFloat(pts.shift())
|
|
276
|
-
const q1 = [p0[0] + (2/3) * (qx - p0[0]), p0[1] + (2/3) * (qy - p0[1])]
|
|
277
|
-
const q2 = [q1[0] + (1/3) * (cx - p0[0]), q1[1] + (1/3) * (cy - p0[1])]
|
|
276
|
+
const q1 = [p0[0] + (2 / 3) * (qx - p0[0]), p0[1] + (2 / 3) * (qy - p0[1])]
|
|
277
|
+
const q2 = [q1[0] + (1 / 3) * (cx - p0[0]), q1[1] + (1 / 3) * (cy - p0[1])]
|
|
278
278
|
tmpCode += `${indent}${pathName} = path2.appendBezier({segments: ${segments}, controlPoints: [[${svg2cag(q1, svgUnitsPmm)}], [${svg2cag(q2, svgUnitsPmm)}], [${svg2cag([cx, cy], svgUnitsPmm)}]]}, ${pathName})\n`
|
|
279
279
|
const rf = reflect(qx, qy, cx, cy)
|
|
280
280
|
qx = rf[0]
|
|
@@ -286,8 +286,8 @@ const path = (obj, svgUnitsPmm, svgUnitsX, svgUnitsY, svgUnitsV, params, svgGrou
|
|
|
286
286
|
const p0 = [cx, cy] // previous point
|
|
287
287
|
cx = cx + parseFloat(pts.shift()) // end point
|
|
288
288
|
cy = cy + parseFloat(pts.shift())
|
|
289
|
-
const q1 = [p0[0] + (2/3) * (qx - p0[0]), p0[1] + (2/3) * (qy - p0[1])]
|
|
290
|
-
const q2 = [q1[0] + (1/3) * (cx - p0[0]), q1[1] + (1/3) * (cy - p0[1])]
|
|
289
|
+
const q1 = [p0[0] + (2 / 3) * (qx - p0[0]), p0[1] + (2 / 3) * (qy - p0[1])]
|
|
290
|
+
const q2 = [q1[0] + (1 / 3) * (cx - p0[0]), q1[1] + (1 / 3) * (cy - p0[1])]
|
|
291
291
|
tmpCode += `${indent}${pathName} = path2.appendBezier({segments: ${segments}, controlPoints: [[[${svg2cag(q1, svgUnitsPmm)}], [${svg2cag(q2, svgUnitsPmm)}], [${svg2cag([cx, cy], svgUnitsPmm)}]]}, ${pathName})\n`
|
|
292
292
|
const rf = reflect(qx, qy, cx, cy)
|
|
293
293
|
qx = rf[0]
|
|
@@ -299,8 +299,8 @@ const path = (obj, svgUnitsPmm, svgUnitsX, svgUnitsY, svgUnitsV, params, svgGrou
|
|
|
299
299
|
const p0 = [cx, cy] // previous point
|
|
300
300
|
cx = parseFloat(pts.shift()) // end point
|
|
301
301
|
cy = parseFloat(pts.shift())
|
|
302
|
-
const q1 = [p0[0] + (2/3) * (qx - p0[0]), p0[1] + (2/3) * (qy - p0[1])]
|
|
303
|
-
const q2 = [q1[0] + (1/3) * (cx - p0[0]), q1[1] + (1/3) * (cy - p0[1])]
|
|
302
|
+
const q1 = [p0[0] + (2 / 3) * (qx - p0[0]), p0[1] + (2 / 3) * (qy - p0[1])]
|
|
303
|
+
const q2 = [q1[0] + (1 / 3) * (cx - p0[0]), q1[1] + (1 / 3) * (cy - p0[1])]
|
|
304
304
|
tmpCode += `${indent}${pathName} = path2.appendBezier({segments: ${segments}, controlPoints: [[[${svg2cag(q1, svgUnitsPmm)}], [${svg2cag(q2, svgUnitsPmm)}], [${svg2cag([cx, cy], svgUnitsPmm)}]]}, ${pathName})\n`
|
|
305
305
|
const rf = reflect(qx, qy, cx, cy)
|
|
306
306
|
qx = rf[0]
|
|
@@ -326,9 +326,7 @@ test('deserialize : instantiate svg (path: with bezier) to objects', (t) => {
|
|
|
326
326
|
</svg>`
|
|
327
327
|
|
|
328
328
|
observed = deserialize({ output: 'geometry', target: 'geom2', addMetaData: false }, sourceSvg)
|
|
329
|
-
t.is(observed.length,
|
|
330
|
-
shape = observed[0]
|
|
331
|
-
t.is(shape.points.length, 14) // open path
|
|
329
|
+
t.is(observed.length, 0) // open path
|
|
332
330
|
|
|
333
331
|
observed = deserialize({ output: 'geometry', target: 'path', addMetaData: false }, sourceSvg)
|
|
334
332
|
t.is(observed.length, 2)
|
|
@@ -344,9 +342,7 @@ test('deserialize : instantiate svg (path: with bezier) to objects', (t) => {
|
|
|
344
342
|
</svg>`
|
|
345
343
|
|
|
346
344
|
observed = deserialize({ output: 'geometry', target: 'geom2', addMetaData: false }, sourceSvg)
|
|
347
|
-
t.is(observed.length,
|
|
348
|
-
shape = observed[0]
|
|
349
|
-
t.is(shape.points.length, 29) // open path
|
|
345
|
+
t.is(observed.length, 0) // open path
|
|
350
346
|
|
|
351
347
|
observed = deserialize({ output: 'geometry', target: 'path', addMetaData: false }, sourceSvg)
|
|
352
348
|
t.is(observed.length, 1)
|
|
@@ -420,13 +416,11 @@ test('deserialize : instantiate svg produced by inkscape to objects', (t) => {
|
|
|
420
416
|
`
|
|
421
417
|
|
|
422
418
|
let observed = deserialize({ filename: 'inkscape', output: 'geometry', target: 'geom2', addMetaData: false }, sourceSvg)
|
|
423
|
-
t.is(observed.length,
|
|
419
|
+
t.is(observed.length, 1)
|
|
424
420
|
let shape = observed[0]
|
|
425
|
-
t.is(shape.outlines.length,
|
|
421
|
+
t.is(shape.outlines.length, 2)
|
|
426
422
|
t.is(shape.outlines[0].length, 19)
|
|
427
|
-
shape
|
|
428
|
-
t.is(shape.outlines.length, 1)
|
|
429
|
-
t.is(shape.outlines[0].length, 20)
|
|
423
|
+
t.is(shape.outlines[1].length, 20)
|
|
430
424
|
|
|
431
425
|
observed = deserialize({ output: 'geometry', target: 'path', addMetaData: false }, sourceSvg)
|
|
432
426
|
t.is(observed.length, 2)
|
|
@@ -446,13 +440,11 @@ test('deserialize : instantiate shape with a hole to objects', (t) => {
|
|
|
446
440
|
`
|
|
447
441
|
|
|
448
442
|
let observed = deserialize({ output: 'geometry', target: 'geom2', addMetaData: false }, sourceSvg)
|
|
449
|
-
t.is(observed.length,
|
|
443
|
+
t.is(observed.length, 1)
|
|
450
444
|
let shape = observed[0]
|
|
451
|
-
t.is(shape.outlines.length,
|
|
452
|
-
t.is(shape.outlines[0].length, 38)
|
|
453
|
-
shape = observed[1]
|
|
454
|
-
t.is(shape.outlines.length, 1)
|
|
445
|
+
t.is(shape.outlines.length, 2)
|
|
455
446
|
t.is(shape.outlines[0].length, 38)
|
|
447
|
+
t.is(shape.outlines[1].length, 38)
|
|
456
448
|
|
|
457
449
|
observed = deserialize({ output: 'geometry', target: 'path', addMetaData: false }, sourceSvg)
|
|
458
450
|
t.is(observed.length, 2)
|
|
@@ -472,9 +464,9 @@ test('deserialize : instantiate shape with a nested hole to objects', (t) => {
|
|
|
472
464
|
`
|
|
473
465
|
|
|
474
466
|
let observed = deserialize({ output: 'geometry', target: 'geom2', addMetaData: false }, sourceSvg)
|
|
475
|
-
t.is(observed.length,
|
|
467
|
+
t.is(observed.length, 1)
|
|
476
468
|
let shape = observed[0]
|
|
477
|
-
t.is(shape.outlines.length,
|
|
469
|
+
t.is(shape.outlines.length, 4)
|
|
478
470
|
t.is(shape.outlines[0].length, 38)
|
|
479
471
|
|
|
480
472
|
observed = deserialize({ output: 'geometry', target: 'path', addMetaData: false }, sourceSvg)
|