Files
cut-abstractions/tests/dev1/dataHandle/common/base/Dxf.ts
2025-07-22 18:22:31 +08:00

491 lines
10 KiB
TypeScript

export class DxfWritor
{
layers: WeakSet<Layer>
activeLayer: Layer
lineTypes: WeakSet<LineType>
offX = 0
offY = 0 // 基点
constructor()
{
this.layers = new WeakSet()
this.activeLayer = null
this.lineTypes = new WeakSet()
for (let i = 0; i < DrawingType.LINE_TYPES.length; ++i)
{
this.addLineType(
DrawingType.LINE_TYPES[i].name,
DrawingType.LINE_TYPES[i].description,
DrawingType.LINE_TYPES[i].elements,
)
}
for (let i = 0; i < DrawingType.LAYERS.length; ++i)
{
this.addLayer(
DrawingType.LAYERS[i].name,
DrawingType.LAYERS[i].colorNumber,
DrawingType.LAYERS[i].lineTypeName,
)
}
this.setActiveLayer('0')
}
/**
* @param {string} name
* @param {string} description
* @param {Array} elements - if elem > 0 it is a line, if elem < 0 it is gap, if elem == 0.0 it is a
*/
addLineType(name, description, elements)
{
this.lineTypes[name] = new LineType(name, description, elements)
return this
}
addLayer(name, colorNumber, lineTypeName)
{
this.layers[name] = new Layer(name, colorNumber, lineTypeName)
return this
}
/** 设置当前图层 白=0, 红=1, 黄=2, 绿=3,CYAN=4,BLUE=5,MAGENTA=6 */
setActiveLayer(name)
{
this.activeLayer = this.layers[name]
return this
}
setOffset(x1, y1)
{
this.offX = x1
this.offY = y1
}
clear()
{
}
drawLine(x1, y1, x2, y2)
{
this.activeLayer.addShape(new Line(x1 + this.offX, y1 + this.offY, x2 + this.offX, y2 + this.offY))
return this
}
drawRect(x1, y1, w, h)
{
x1 = x1 + this.offX
y1 = y1 + this.offY
this.activeLayer.addShape(new Line(x1, y1, x1 + w, y1))
this.activeLayer.addShape(new Line(x1 + w, y1, x1 + w, y1 + h))
this.activeLayer.addShape(new Line(x1 + w, y1 + h, x1, y1 + h))
this.activeLayer.addShape(new Line(x1, y1 + h, x1, y1))
return this
}
/**
* @param {number} x1 - Center x
* @param {number} y1 - Center y
* @param {number} r - radius
* @param {number} startAngle - degree
* @param {number} endAngle - degree
*/
drawArc(x1, y1, r, startAngle, endAngle)
{
this.activeLayer.addShape(new Arc(x1 + this.offX, y1 + this.offY, r, startAngle, endAngle))
return this
}
/**
* @param {number} x1 - Center x
* @param {number} y1 - Center y
* @param {number} r - radius
*/
drawCircle(x1, y1, r)
{
this.activeLayer.addShape(new Circle(x1 + this.offX, y1 + this.offY, r))
return this
}
/**
* @param {number} x1 - x
* @param {number} y1 - y
* @param {number} height - Text height
* @param {number} rotation - Text rotation
* @param {string} value - the string itself
*/
drawText(x1, y1, height, rotation, value)
{
this.activeLayer.addShape(new Text(x1 + this.offX, y1 + this.offY, height, rotation, value))
return this
}
/**
* @param {Array} points - Array of points like [ [x1, y1,r], [x2, y2,r]... ]
*/
drawPolyline(points, isClose = false)
{
for (const p of points)
{
p.x += this.offX
p.y += this.offY
}
this.activeLayer.addShape(new Polyline(points, isClose))
return this
}
_getDxfLtypeTable()
{
let s = '0\nTABLE\n' // start table
s += '2\nLTYPE\n' // name table as LTYPE table
for (let lineTypeName in this.lineTypes)
{
s += this.lineTypes[lineTypeName].toDxfString()
}
s += '0\nENDTAB\n' // end table
return s
}
_getDxfLayerTable()
{
let s = '0\nTABLE\n' // start table
s += '2\nLAYER\n' // name table as LAYER table
for (let layerName in this.layers)
{
s += this.layers[layerName].toDxfString()
}
s += '0\nENDTAB\n'
return s
}
toDxfString()
{
let s = ''
// start section
s += '0\nSECTION\n'
// name section as TABLES section
s += '2\nTABLES\n'
s += this._getDxfLtypeTable()
s += this._getDxfLayerTable()
// end section
s += '0\nENDSEC\n'
// ENTITES section
s += '0\nSECTION\n'
s += '2\nENTITIES\n'
for (let layerName in this.layers)
{
let layer = this.layers[layerName]
s += layer.shapesToDxf()
// let shapes = layer.getShapes();
}
s += '0\nENDSEC\n'
// close file
s += '0\nEOF'
return s
}
}
namespace DrawingType
{
// AutoCAD Color Index (ACI)
// http://sub-atomic.com/~moses/acadcolors.html
export const ACI = {
LAYER: 0,
RED: 1,
YELLOW: 2,
GREEN: 3,
CYAN: 4,
BLUE: 5,
MAGENTA: 6,
WHITE: 7,
}
export const LINE_TYPES = [
{ name: 'CONTINUOUS', description: '______', elements: [] },
{ name: 'DASHED', description: '_ _ _ ', elements: [5.0, -5.0] },
{ name: 'DOTTED', description: '. . . ', elements: [0.0, -5.0] },
]
export const LAYERS = [
{ name: '0', colorNumber: ACI.WHITE, lineTypeName: 'CONTINUOUS' },
{ name: '1', colorNumber: ACI.RED, lineTypeName: 'CONTINUOUS' },
{ name: '2', colorNumber: ACI.YELLOW, lineTypeName: 'CONTINUOUS' },
{ name: '3', colorNumber: ACI.GREEN, lineTypeName: 'CONTINUOUS' },
{ name: '4', colorNumber: ACI.CYAN, lineTypeName: 'CONTINUOUS' },
{ name: '5', colorNumber: ACI.BLUE, lineTypeName: 'CONTINUOUS' },
{ name: '6', colorNumber: ACI.MAGENTA, lineTypeName: 'CONTINUOUS' },
]
}
export class LineType
{
name: string
description: string
elements: any[]
/**
* @param {string} name
* @param {string} description
* @param {Array} elements - if elem > 0 it is a line, if elem < 0 it is gap, if elem == 0.0 it is a
*/
constructor(name, description, elements)
{
this.name = name
this.description = description
this.elements = elements
}
/**
* @link https://www.autodesk.com/techpubs/autocad/acadr14/dxf/ltype_al_u05_c.htm
*/
toDxfString()
{
let s = '0\nLTYPE\n'
s += '72\n65\n'
s += '70\n64\n'
s += `2\n${this.name}\n`
s += `3\n${this.description}\n`
s += `73\n${this.elements.length}\n`
s += `40\n${this.getElementsSum()}\n`
for (let i = 0; i < this.elements.length; ++i)
{
s += `49\n${this.elements[i]}\n`
}
return s
}
getElementsSum()
{
let sum = 0
for (let i = 0; i < this.elements.length; ++i)
{
sum += Math.abs(this.elements[i])
}
return sum
}
}
export class Layer
{
name: string
colorNumber: string
lineTypeName: string
shapes: any[]
constructor(name, colorNumber, lineTypeName)
{
this.name = name
this.colorNumber = colorNumber
this.lineTypeName = lineTypeName
this.shapes = []
}
toDxfString()
{
let s = '0\nLAYER\n'
s += '70\n64\n'
s += `2\n${this.name}\n`
s += `62\n${this.colorNumber}\n`
s += `6\n${this.lineTypeName}\n`
return s
}
addShape(shape)
{
this.shapes.push(shape)
shape.layer = this
}
getShapes()
{
return this.shapes
}
shapesToDxf()
{
let s = ''
for (let i = 0; i < this.shapes.length; ++i)
{
s += this.shapes[i].toDxfString()
}
return s
}
}
export class Arc
{
x1: number
y1: number
r: number
startAngle: number
endAngle: number
layer: Layer
/**
* @param {number} x1 - Center x
* @param {number} y1 - Center y
* @param {number} r - radius
* @param {number} startAngle - degree
* @param {number} endAngle - degree
*/
constructor(x1, y1, r, startAngle, endAngle)
{
this.x1 = x1
this.y1 = y1
this.r = r
this.startAngle = startAngle
this.endAngle = endAngle
}
toDxfString()
{
// https://www.autodesk.com/techpubs/autocad/acadr14/dxf/line_al_u05_c.htm
let s = `0\nARC\n`
s += `8\n${this.layer.name}\n`
s += `10\n${this.x1}\n20\n${this.y1}\n30\n0\n`
s += `40\n${this.r}\n50\n${this.startAngle}\n51\n${this.endAngle}\n`
return s
}
}
export class Circle
{
x1: number
y1: number
r: number
layer: Layer
/**
* @param {number} x1 - Center x
* @param {number} y1 - Center y
* @param {number} r - radius
*/
constructor(x1, y1, r)
{
this.x1 = x1
this.y1 = y1
this.r = r
}
toDxfString()
{
// https://www.autodesk.com/techpubs/autocad/acadr14/dxf/circle_al_u05_c.htm
let s = `0\nCIRCLE\n`
s += `8\n${this.layer.name}\n`
s += `10\n${this.x1}\n20\n${this.y1}\n30\n0\n`
s += `40\n${this.r}\n`
return s
}
}
export class Line
{
x1: number
y1: number
x2: number
y2: number
layer: Layer
constructor(x1: number, y1: number, x2: number, y2: number)
{
this.x1 = x1
this.y1 = y1
this.x2 = x2
this.y2 = y2
}
toDxfString()
{
// https://www.autodesk.com/techpubs/autocad/acadr14/dxf/line_al_u05_c.htm
let s = `0\nLINE\n`
s += `8\n${this.layer.name}\n`
s += `10\n${this.x1}\n20\n${this.y1}\n30\n0\n`
s += `11\n${this.x2}\n21\n${this.y2}\n31\n0\n`
return s
}
}
export class Polyline
{
points: any[]
isClose = false
layer: Layer
/**
* @param {Array} points - Array of points like [ [x1, y1,r], [x2, y2,r]... ]
*/
constructor(points, isClose)
{
this.points = points
this.isClose = isClose
}
toDxfString()
{
// https://www.autodesk.com/techpubs/autocad/acad2000/dxf/polyline_dxf_06.htm
// https://www.autodesk.com/techpubs/autocad/acad2000/dxf/vertex_dxf_06.htm
let s = `0\nPOLYLINE\n`
s += `8\n${this.layer.name}\n`
s += `66\n1\n70\n${this.isClose ? 1 : 0}\n`
for (let i = 0; i < this.points.length; ++i)
{
s += `0\nVERTEX\n`
s += `8\n${this.layer.name}\n`
s += `70\n0\n`
s += `10\n${this.points[i].x}\n20\n${this.points[i].y}\n42\n${this.points[i].r}\n`
}
s += `0\nSEQEND\n`
return s
}
}
export class Text
{
x1: number
y1: number
height: number
rotation: number
value: string
layer: Layer
/**
* @param {number} x1 - x
* @param {number} y1 - y
* @param {number} height - Text height
* @param {number} rotation - Text rotation
* @param {string} value - the string itself
*/
constructor(x1, y1, height, rotation, value)
{
this.x1 = x1
this.y1 = y1
this.height = height
this.rotation = rotation
this.value = value
}
toDxfString()
{
// https://www.autodesk.com/techpubs/autocad/acadr14/dxf/text_al_u05_c.htm
let s = `0\nTEXT\n`
s += `8\n${this.layer.name}\n`
s += `1\n${this.value}\n`
s += `10\n${this.x1}\n20\n${this.y1}\n30\n0\n`
s += `40\n${this.height}\n50\n${this.rotation}\n`
return s
}
}