248 lines
4 KiB
JavaScript
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
|