import fs from 'fs' import { join } from 'path' import expect from 'expect' import { parseString, toSVG } from '../../src' const dxfsFilenames = [ 'elliptical-arc1.dxf', 'elliptical-arc2.dxf', 'elliptical-arc3.dxf', 'elliptical-arc4.dxf', 'elliptical-arc5.dxf', 'elliptical-arc6.dxf', 'elliptical-arc7.dxf', 'elliptical-arc8.dxf', 'elliptical-arc9.dxf', 'elliptical-arc10.dxf', 'elliptical-arc11.dxf', 'elliptical-arc12.dxf', 'elliptical-arc13.dxf', 'elliptical-arc14.dxf', 'arc15.dxf', 'arc16.dxf', 'arc17.dxf', 'squircle2.dxf', ] // Load and parse DXFs const dxfs = dxfsFilenames.reduce((dxfObj, dxfFilename) => { dxfObj[dxfFilename] = parseString( fs.readFileSync(join(__dirname, '/../resources/' + dxfFilename), 'utf-8'), ) return dxfObj }, {}) // Helper functions for testing SVGs const approx = (a, b) => Math.abs(a - b) < 1e-12 expect.extend({ toMatchViewbox(received, a, b, c, d) { // Use naive regex to match numbers const re = /viewBox="([-0-9.e]+) ([-0-9.e]+) ([-0-9.e]+) ([-0-9.e]+)"/ const result = re.exec(received) if ( result && approx(parseFloat(result[1]), a) && approx(parseFloat(result[2]), b) && approx(parseFloat(result[3]), c) && approx(parseFloat(result[4]), d) ) { return { pass: true, message: () => `expected ${received} not to contain 'viewBox="${a} ${b} ${c} ${d}"'`, } } else { return { pass: false, message: () => `expected ${received} to contain 'viewBox="${a} ${b} ${c} ${d}"'`, } } }, toMatchArc(received, a, b, c, d, e, f, g, h, i) { const re = /path d="M ([-0-9.e]+) ([-0-9.e]+) A ([-0-9.e]+) ([-0-9.e]+) ([-0-9.e]+) ([-0-9.e]+) ([-0-9.e]+) ([-0-9.e]+) ([-0-9.e]+)"/ const result = re.exec(received) if ( result && approx(parseFloat(result[1]), a) && approx(parseFloat(result[2]), b) && approx(parseFloat(result[3]), c) && approx(parseFloat(result[4]), d) && approx(parseFloat(result[5]), e) && approx(parseFloat(result[6]), f) && approx(parseFloat(result[7]), g) && approx(parseFloat(result[8]), h) && approx(parseFloat(result[9]), i) ) { return { pass: true, message: () => `expected ${received} not to contain 'path d="M ${a} ${b} A ${c} ${d} ${e} ${f} ${g} ${h} ${i}"'`, } } else { return { pass: false, message: () => `expected ${received} to contain 'path d="M ${a} ${b} A ${c} ${d} ${e} ${f} ${g} ${h} ${i}"'`, } } }, toBePolyline(received) { const re = /path d="([ML][-0-9.e]+,[-0-9.e]+)+"/ const result = re.exec(received) if (result) { return { pass: true, message: () => `expected ${received} to not be a path containing only M and L commands`, } } else { return { pass: false, message: () => `expected ${received} to be a path containing only M and L commands`, } } }, }) describe('toSVG', () => { it('elliptical arcs', () => { const svg1 = toSVG(dxfs['elliptical-arc1.dxf']) expect(svg1).toMatchViewbox(0, -5, 10, 5) expect(svg1).toMatchArc(10, 0, 10, 5, 0, 0, 1, 0, 5) const svg2 = toSVG(dxfs['elliptical-arc2.dxf']) expect(svg2).toMatchViewbox( 5, -4.3301270189221945, 3.66025403784439, 1.830127018922195, ) expect(svg2).toMatchArc( 8.660254037844387, 2.5, 10, 5, 0, 0, 1, 5, 4.3301270189221945, ) const svg3 = toSVG(dxfs['elliptical-arc3.dxf']) expect(svg3).toMatchViewbox(-10, -5, 17.071067811865476, 7.867882181755233) expect(svg3).toMatchArc( 7.0710678118654755, 3.5355339059327373, 10, 5, 0, 0, 1, -8.191520442889914, -2.8678821817552325, ) const svg4 = toSVG(dxfs['elliptical-arc4.dxf']) expect(svg4).toMatchViewbox(0, -5, 10, 5) expect(svg4).toMatchArc(10, 0, 10, 5, 180, 0, 1, 0, 5) const svg5 = toSVG(dxfs['elliptical-arc5.dxf']) expect(svg5).toMatchViewbox( -3.5355339059327404, -7.842193570679061, 10.535533905932741, 4.306659664746326, ) expect(svg5).toMatchArc( 7, 7, 9.899494936611665, 5, 45, 0, 1, -3.53553390593274, 3.535533905932735, ) const svg6 = toSVG(dxfs['elliptical-arc6.dxf']) expect(svg6).toMatchViewbox( -6.154864169189802, -6.6858457603474335, 12.309728338379603, 14.817121617113303, ) expect(svg6).toMatchArc( -2.7017524810471167, 6.6858457603474335, 8.246211251235321, 6, 75.96375653207353, 1, 1, 5.530179605793307, 4.627862738637326, ) const svg7 = toSVG(dxfs['elliptical-arc7.dxf']) expect(svg7).toMatchViewbox( -167.88778995326126, -129.36546401373693, 319.9335798426189, 189.91283752909544, ) expect(svg7).toMatchArc( 152.04578988935765, -18.03933100382215, 188.7669481278684, 96.37827861800855, -32.118022210114795, 1, 1, -81.36053316126296, -60.54737351535849, ) const svg8 = toSVG(dxfs['elliptical-arc8.dxf']) expect(svg8).toMatchViewbox( 3.4781225959317084, -49.009105281414, 55.15869905572283, 15.029496981434129, ) expect(svg8).toMatchArc( 58.63682165165453, 48.26215307468564, 80.93400088961376, 14.444639918326656, 172.54570118725155, 0, 1, 11.64284740886555, 33.97960829997985, ) const svg9 = toSVG(dxfs['elliptical-arc9.dxf']) expect(svg9).toMatchViewbox( -118.07395417897287, -17.676045821027287, 216.90220929420212, 13.244102801798334, ) expect(svg9).toMatchArc( -118.07395417897287, 17.6760458210273, 289.26080360117925, 134.5498578288584, -0.4951975183272285, 0, 1, 98.82825511522925, 11.356781878370896, ) const svg10 = toSVG(dxfs['elliptical-arc10.dxf']) expect(svg10).toMatchViewbox( -120.64872816971088, 16.151626150687072, 71.29745633942176, 98.19674769862587, ) expect(svg10).toMatchArc( -81.02670163715118, -27.945143148808462, 56.930330229149384, 20.98617723085445, 57.00777591273486, 1, 1, -72.10048373873673, -21.023087104240282, ) const svg11 = toSVG(dxfs['elliptical-arc11.dxf']) expect(svg11).toMatchViewbox(-10, -10, 10, 20) expect(svg11).toMatchArc(0, 10, 10, 10, 90, 1, 1, 0, -10) const svg12 = toSVG(dxfs['elliptical-arc12.dxf']) expect(svg12).toMatchViewbox(-10, -10, 20, 10) expect(svg12).toMatchArc(10, 0, 10, 10, -90, 0, 1, -10, 0) const svg13 = toSVG(dxfs['elliptical-arc13.dxf']) expect(svg13).toMatchViewbox( -1.7632895890672167, 1.5992030653460318, 6.174337259217236, 7.312158352051181, ) expect(svg13).toMatchArc( 4.411047670150015, -2.459236818521333, 37.191963391294095, 6.5832748294449015, 144.46232220802563, 0, 1, 1.4844885427615573, -8.91136141739722, ) const svg14 = toSVG(dxfs['elliptical-arc14.dxf']) expect(svg14).toMatchViewbox( -12.414567247795588, -183.83824901758035, 305.3491133082473, 293.612508149379, ) expect(svg14).toMatchArc( 80.13575797098328, 183.83824901758032, 160.3652081967906, 151.7760801446391, 160.3221424787954, 1, 1, 292.9345460604517, -23.32855250669232, ) const svg15 = toSVG(dxfs['arc15.dxf']) expect(svg15).toMatchViewbox( -10.401676865889314, -54.94802533287292, 54.844949682905835, 20.520461073710003, ) expect(svg15).toMatchArc( 44.44327281701652, 46.73192738041983, 35.44802533287292, 35.44802533287292, 0, 0, 1, -10.401676865889314, 34.42756425916292, ) const svg16 = toSVG(dxfs['arc16.dxf']) expect(svg16).toMatchViewbox( -14.41854547874551, -16.16854547874551, 62.83709095749103, 62.83709095749103, ) expect(svg16).toMatchArc( 4.131265300907282, -43.912181829797376, 31.41854547874551, 31.41854547874551, 0, 1, 1, -14.09320807604486, -19.759701934693545, ) const svg17 = toSVG(dxfs['arc17.dxf']) expect(svg17).toMatchViewbox( -48.5, -23.649355077918734, 94.75, 54.899355077918806, ) expect(svg17).toMatchArc( 46.25, 21.75, 81.76917590658614, 81.76917590658614, 0, 0, 1, -48.5, -31.25, ) }) it('splines with weights should use polyline, not bezier', () => { const squircle2 = toSVG(dxfs['squircle2.dxf']) expect(squircle2).toBePolyline() }) })