1
0
Fork 0
freesewing/packages/plugin-export-dxf/src/dxf.js
2021-04-24 10:16:31 +02:00

248 lines
4 KiB
JavaScript

import { name, version, description, author, license } from '../package.json'
function Dxf(config) {
this.config = config
}
// Round to 2 decimals because DXF is stupid
Dxf.prototype.round = function (val) {
return Math.round(val * 100) / 100
}
/** Returns DXF code for optional banner */
Dxf.prototype.banner = function (pattern) {
return `999
${name.slice(1)} | v${version}
999
${description}
999
(c) ${new Date().getFullYear()} ${author}
999
License: ${license}
999
Pattern: ${pattern.config.name} | v${pattern.config.version}
999
Export date: ${new Date().toISOString()}`
}
/** Returns DXF code for tables */
Dxf.prototype.tables = function (tables) {
let dxf = `
0
SECTION
2
TABLES`
for (let lineType of tables.lineTypes)
dxf += `
0
TABLE
2
LTYPE
0
LTYPE
2
${lineType.name}
3
${lineType.description}
72
65
73
0
40
0.00
0
ENDTAB`
for (let layer of tables.layers)
dxf += `
0
TABLE
2
LAYER
0
LAYER
2
${layer.name}
62
${layer.color}
6
${layer.lineType}
0
ENDTAB`
dxf += `
0
ENDSEC`
return dxf
}
/** Returns DXF code to close/end a DXF file */
Dxf.prototype.footer = function () {
return `
0
EOF
`
}
/** Returns DXF code for a line */
Dxf.prototype.line = function (to, layer) {
return `
0
VERTEX
8
${layer}
10
${this.round(to.x)}
20
${this.round(to.y)}`
}
/** Returns DXF code for a curve */
Dxf.prototype.curve = function (from, cp1, cp2, to, layer, part) {
let { Path } = part.shorthand()
let path = new Path().move(from).curve(cp1, cp2, to)
let steps = Math.floor(path.length() / this.config.precision)
let current
let dxf = ''
for (let i = 1; i < steps; i++) {
current = path.shiftAlong(i * this.config.precision)
dxf += this.line(current, layer)
}
if (current.dist(to) > 0.1) dxf += this.line(to, layer)
return dxf
}
/** Returns DXF code for a Path object */
Dxf.prototype.path = function (path, layer, part) {
let dxf = `
0
POLYLINE
8
${layer}
70
1`
let current, start
for (let op of path.ops) {
switch (op.type) {
case 'move':
start = op.to
dxf += this.line(op.to, layer)
break
case 'line':
dxf += this.line(op.to, layer)
break
case 'curve':
dxf += this.curve(current, op.cp1, op.cp2, op.to, layer, part)
break
case 'close':
dxf += this.line(start, layer)
break
case 'noop':
break
default:
throw new Error(`Unsupported path operation: ${op.type}`)
}
current = op.to
}
dxf += `
0
SEQEND`
return dxf
}
/** Returns blocs portion of the DXF code for a Part object */
Dxf.prototype.partBlocks = function (part, name, layer = 1) {
let dxf = `
0
BLOCK
8
${layer}
2
${name}
70
0
10
0.00
20
0.00`
for (let key in part.paths) {
this.pathName = key
this.partName = name
let path = part.paths[key]
if (path.render) dxf += this.path(path, layer, part)
}
dxf += `
0
ENDBLK`
return dxf
}
/** Returns entities portion of the DXF code for a Part object */
Dxf.prototype.partEntities = function (part, name, layer = 1) {
return `
0
INSERT
8
${layer}
2
${name}
10
0.00
20
0.00`
}
/** Exports (drafted) pattern as DXF-ASTM */
Dxf.prototype.render = function (pattern) {
// Ensure pattern layout
pattern.pack()
// Tables structure
let tables = {
lineTypes: [
{
name: 'CONTINUOUS',
description: 'SOLIDLINE',
},
],
layers: [
{
name: 1,
color: 7,
lineType: 'CONTINIOUS',
},
],
}
let dxf = ''
dxf += this.banner(pattern)
dxf += this.tables(tables)
dxf += `
0
SECTION
2
BLOCKS`
for (let partId in pattern.parts) {
if (pattern.parts[partId].render) dxf += this.partBlocks(pattern.parts[partId], partId)
}
dxf += `
0
ENDSEC
0
SECTION
2
ENTITIES`
for (let partId in pattern.parts) {
if (pattern.parts[partId].render) dxf += this.partEntities(pattern.parts[partId], partId)
}
dxf += `
0
ENDSEC`
dxf += this.footer()
return dxf
}
export default Dxf