From 6178746ee887eb1fbacb060cfc952d07d5264173 Mon Sep 17 00:00:00 2001 From: Ibon Eskudero Date: Tue, 29 Nov 2022 10:22:45 +0100 Subject: [PATCH] feat: LTYPE table parsing (#121) --- src/handlers/tables.js | 78 ++++- src/parseString.js | 2 +- test/unit/tables.test.js | 695 +++++++++++++++++++++++++++++++++++++++ 3 files changed, 773 insertions(+), 2 deletions(-) create mode 100644 test/unit/tables.test.js diff --git a/src/handlers/tables.js b/src/handlers/tables.js index a9abcd1..d369a1e 100644 --- a/src/handlers/tables.js +++ b/src/handlers/tables.js @@ -1,5 +1,79 @@ import logger from '../util/logger' +const ltypeHandler = (tuples) => { + let element = null + let offset = null + return tuples.reduce((layer, tuple) => { + const type = tuple[0] + const value = tuple[1] + //https://documentation.help/AutoCAD-DXF/WS1a9193826455f5ff18cb41610ec0a2e719-7a4f.htm + switch (type) { + case 2: + layer.name = value + break + case 3: + layer.description = value + break + case 70: + //Standard flag values (bit-coded values): + // 16 = If set, table entry is externally dependent on an xref + // 32 = If both this bit and bit 16 are set, the externally dependent xref has been successfully resolved + // 64 = If set, the table entry was referenced by at least one entity in the drawing the last time the drawing was edited. (This flag is for the benefit of AutoCAD commands. It can be ignored by most programs that read DXF files and need not be set by programs that write DXF files) + layer.flag = value + break + case 72: + //Alignment code (value is always 65, the ASCII code for A): + layer.alignment = value + break + case 73: + layer.elementCount = parseInt(value) + break + case 40: + layer.patternLength = value + break + case 49: { + element = Object.create({ scales: [], offset: [] }); + element.length = value + layer.pattern.push( element ); + } + break + case 74: + //Complex linetype element type (one per element). Default is 0 (no embedded shape/text) (bit-coded values) + // 1 = If set, code 50 specifies an absolute rotation; if not set, code 50 specifies a relative rotation + // 2 = Embedded element is a text string + // 4 = Embedded element is a shape + element.shape = value + break + case 75: + element.shapeNumber = value + break + case 340: + element.styleHandle = value + break + case 46: + element.scales.push( value ) + break + case 50: + element.rotation = value + break + case 44: + offset = Object.create( { x: value, y: 0 } ) + element.offset.push( offset ) + break + case 45: + offset.y = value + break + case 9: + element.text = value + break + default: + } + return layer + }, { type: 'LTYPE', + pattern: [] + }) +} + const layerHandler = (tuples) => { return tuples.reduce( (layer, tuple) => { @@ -239,11 +313,12 @@ export default (tuples) => { let stylesTuples = [] let layersTuples = [] let vPortTuples = [] + let ltypeTuples = [] tableGroups.forEach((group) => { if (group[0][1] === 'STYLE') { stylesTuples = group } else if (group[0][1] === 'LTYPE') { - logger.warn('LTYPE in tables not supported') + ltypeTuples = group } else if (group[0][1] === 'LAYER') { layersTuples = group } else if (group[0][1] === 'VPORT') { @@ -255,5 +330,6 @@ export default (tuples) => { layers: tableHandler(layersTuples, 'LAYER', layerHandler), styles: tableHandler(stylesTuples, 'STYLE', styleHandler), vports: tableHandler(vPortTuples, 'VPORT', vPortHandler), + ltypes: tableHandler(ltypeTuples,'LTYPE', ltypeHandler) } } diff --git a/src/parseString.js b/src/parseString.js index c1ecce3..154f671 100644 --- a/src/parseString.js +++ b/src/parseString.js @@ -87,7 +87,7 @@ export default (string) => { blocks: [], entities: [], objects: { layouts: [] }, - tables: { layers: {}, styles: {} }, + tables: { layers: {}, styles: {}, ltypes: {}} }) return result } diff --git a/test/unit/tables.test.js b/test/unit/tables.test.js new file mode 100644 index 0000000..e794828 --- /dev/null +++ b/test/unit/tables.test.js @@ -0,0 +1,695 @@ +import fs from 'fs' +import { join } from 'path' +import expect from 'expect' + +import { parseString } from '../../src' +const dxfContents = fs.readFileSync( + join(__dirname, '/../resources/lines.dxf'), + 'utf-8', +) + +describe('tables', () => { + it('can parse the ltype', () => { + const parsed = parseString(dxfContents) + expect(parsed.tables.ltypes).toEqual({ + ByBlock: { + type: "LTYPE", + pattern: [], + name: "ByBlock", + flag: 0, + description: "", + alignment: 65, + elementCount: 0, + patternLength: 0 + }, + ByLayer: { + type: "LTYPE", + pattern: [], + name: "ByLayer", + flag: 0, + description: "", + alignment: 65, + elementCount: 0, + patternLength: 0 + }, + Continuous: { + type: "LTYPE", + pattern: [], + name: "Continuous", + flag: 0, + description: "Solid line", + alignment: 65, + elementCount: 0, + patternLength: 0 + }, + DOT: { + type: "LTYPE", + pattern: [ + { + length: 0, + shape: 0 + }, + { + length: -6.35, + shape: 0 + } + ], + name: "DOT", + flag: 0, + description: "Dot . . . . . . . . . . . . . . . . . . . . . .", + alignment: 65, + elementCount: 2, + patternLength: 6.35 + }, + DOTTINY: { + type: "LTYPE", + pattern: [ + { + length: 0, + shape: 0 + }, + { + length: -0.9525, + shape: 0 + } + ], + name: "DOTTINY", + flag: 0, + description: "Dot (.15x) .....................................", + alignment: 65, + elementCount: 2, + patternLength: 0.9525 + }, + DOT2: { + type: "LTYPE", + pattern: [ + { + length: 0, + shape: 0 + }, + { + length: -3.175, + shape: 0 + } + ], + name: "DOT2", + flag: 0, + description: "Dot (.5x) .....................................", + alignment: 65, + elementCount: 2, + patternLength: 3.175 + }, + DOTX2: { + type: "LTYPE", + pattern: [ + { + length: 0, + shape: 0 + }, + { + length: -12.7, + shape: 0 + } + ], + name: "DOTX2", + flag: 0, + description: "Dot (2x) . . . . . . . . . . . . .", + alignment: 65, + elementCount: 2, + patternLength: 12.7 + }, + DASHED: { + type: "LTYPE", + pattern: [ + { + length: 12.7, + shape: 0 + }, + { + length: -6.35, + shape: 0 + } + ], + name: "DASHED", + flag: 0, + description: "Dashed _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _", + alignment: 65, + elementCount: 2, + patternLength: 19.05 + }, + DASHEDTINY: { + type: "LTYPE", + pattern: [ + { + length: 1.905, + shape: 0 + }, + { + length: -0.9525, + shape: 0 + } + ], + name: "DASHEDTINY", + flag: 0, + description: "Dashed (.15x) _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _", + alignment: 65, + elementCount: 2, + patternLength: 2.8575 + }, + DASHED2: { + type: "LTYPE", + pattern: [ + { + length: 6.35, + shape: 0 + }, + { + length: -3.175, + shape: 0 + } + ], + name: "DASHED2", + flag: 0, + description: "Dashed (.5x) _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _", + alignment: 65, + elementCount: 2, + patternLength: 9.524999999999999 + }, + DASHEDX2: { + type: "LTYPE", + pattern: [ + { + length: 25.4, + shape: 0 + }, + { + length: -12.7, + shape: 0 + } + ], + name: "DASHEDX2", + flag: 0, + description: "Dashed (2x) ____ ____ ____ ____ ____ ___", + alignment: 65, + elementCount: 2, + patternLength: 38.09999999999999 + }, + DASHDOT: { + type: "LTYPE", + pattern: [ + { + length: 12.7, + shape: 0 + }, + { + length: -6.35, + shape: 0 + }, + { + length: 0, + shape: 0 + }, + { + length: -6.35, + shape: 0 + } + ], + name: "DASHDOT", + flag: 0, + description: "Dash dot __ . __ . __ . __ . __ . __ . __ . __", + alignment: 65, + elementCount: 4, + patternLength: 25.4 + }, + DASHDOTTINY: { + type: "LTYPE", + pattern: [ + { + length: 1.905, + shape: 0 + }, + { + length: -0.9525, + shape: 0 + }, + { + length: 0, + shape: 0 + }, + { + length: -0.9525, + shape: 0 + } + ], + name: "DASHDOTTINY", + flag: 0, + description: "Dash dot (.15x) _._._._._._._._._._._._._._._.", + alignment: 65, + elementCount: 4, + patternLength: 3.81 + }, + DASHDOT2: { + type: "LTYPE", + pattern: [ + { + length: 6.35, + shape: 0 + }, + { + length: -3.175, + shape: 0 + }, + { + length: 0, + shape: 0 + }, + { + length: -3.175, + shape: 0 + } + ], + name: "DASHDOT2", + flag: 0, + description: "Dash dot (.5x) _._._._._._._._._._._._._._._.", + alignment: 65, + elementCount: 4, + patternLength: 12.7 + }, + DASHDOTX2: { + type: "LTYPE", + pattern: [ + { + length: 25.4, + shape: 0 + }, + { + length: -12.7, + shape: 0 + }, + { + length: 0, + shape: 0 + }, + { + length: -12.7, + shape: 0 + } + ], + name: "DASHDOTX2", + flag: 0, + description: "Dash dot (2x) ____ . ____ . ____ . ___", + alignment: 65, + elementCount: 4, + patternLength: 50.8 + }, + DIVIDE: { + type: "LTYPE", + pattern: [ + { + length: 12.7, + shape: 0 + }, + { + length: -6.35, + shape: 0 + }, + { + length: 0, + shape: 0 + }, + { + length: -6.35, + shape: 0 + }, + { + length: 0, + shape: 0 + }, + { + length: -6.35, + shape: 0 + } + ], + name: "DIVIDE", + flag: 0, + description: "Divide ____ . . ____ . . ____ . . ____ . . ____", + alignment: 65, + elementCount: 6, + patternLength: 31.75 + }, + DIVIDETINY: { + type: "LTYPE", + pattern: [ + { + length: 1.905, + shape: 0 + }, + { + length: -0.9525, + shape: 0 + }, + { + length: 0, + shape: 0 + }, + { + length: -0.9525, + shape: 0 + }, + { + length: 0, + shape: 0 + }, + { + length: -0.9525, + shape: 0 + } + ], + name: "DIVIDETINY", + flag: 0, + description: "Divide (.15x) __..__..__..__..__..__..__..__.._", + alignment: 65, + elementCount: 6, + patternLength: 4.7625 + }, + DIVIDE2: { + type: "LTYPE", + pattern: [ + { + length: 6.35, + shape: 0 + }, + { + length: -3.175, + shape: 0 + }, + { + length: 0, + shape: 0 + }, + { + length: -3.175, + shape: 0 + }, + { + length: 0, + shape: 0 + }, + { + length: -3.175, + shape: 0 + } + ], + name: "DIVIDE2", + flag: 0, + description: "Divide (.5x) __..__..__..__..__..__..__..__.._", + alignment: 65, + elementCount: 6, + patternLength: 15.875 + }, + DIVIDEX2: { + type: "LTYPE", + pattern: [ + { + length: 25.4, + shape: 0 + }, + { + length: -12.7, + shape: 0 + }, + { + length: 0, + shape: 0 + }, + { + length: -12.7, + shape: 0 + }, + { + length: 0, + shape: 0 + }, + { + length: -12.7, + shape: 0 + } + ], + name: "DIVIDEX2", + flag: 0, + description: "Divide (2x) ________ . . ________ . . _", + alignment: 65, + elementCount: 6, + patternLength: 63.5 + }, + BORDER: { + type: "LTYPE", + pattern: [ + { + length: 12.7, + shape: 0 + }, + { + length: -6.35, + shape: 0 + }, + { + length: 12.7, + shape: 0 + }, + { + length: -6.35, + shape: 0 + }, + { + length: 0, + shape: 0 + }, + { + length: -6.35, + shape: 0 + } + ], + name: "BORDER", + flag: 0, + description: "Border __ __ . __ __ . __ __ . __ __ . __ __ .", + alignment: 65, + elementCount: 6, + patternLength: 44.45 + }, + BORDERTINY: { + type: "LTYPE", + pattern: [ + { + length: 1.905, + shape: 0 + }, + { + length: -0.9525, + shape: 0 + }, + { + length: 1.905, + shape: 0 + }, + { + length: -0.9525, + shape: 0 + }, + { + length: 0, + shape: 0 + }, + { + length: -0.9525, + shape: 0 + } + ], + name: "BORDERTINY", + flag: 0, + description: "Border (.15x) __.__.__.__.__.__.__.__.__.__.__.", + alignment: 65, + elementCount: 6, + patternLength: 6.6675 + }, + BORDER2: { + type: "LTYPE", + pattern: [ + { + length: 6.35, + shape: 0 + }, + { + length: -3.175, + shape: 0 + }, + { + length: 6.35, + shape: 0 + }, + { + length: -3.175, + shape: 0 + }, + { + length: 0, + shape: 0 + }, + { + length: -3.175, + shape: 0 + } + ], + name: "BORDER2", + flag: 0, + description: "Border (.5x) __.__.__.__.__.__.__.__.__.__.__.", + alignment: 65, + elementCount: 6, + patternLength: 22.225 + }, + BORDERX2: { + type: "LTYPE", + pattern: [ + { + length: 25.4, + shape: 0 + }, + { + length: -12.7, + shape: 0 + }, + { + length: 25.4, + shape: 0 + }, + { + length: -12.7, + shape: 0 + }, + { + length: 0, + shape: 0 + }, + { + length: -12.7, + shape: 0 + } + ], + name: "BORDERX2", + flag: 0, + description: "Border (2x) ____ ____ . ____ ____ . ___", + alignment: 65, + elementCount: 6, + patternLength: 88.89999999999999 + }, + CENTER: { + type: "LTYPE", + pattern: [ + { + length: 31.75, + shape: 0 + }, + { + length: -6.35, + shape: 0 + }, + { + length: 6.35, + shape: 0 + }, + { + length: -6.35, + shape: 0 + } + ], + name: "CENTER", + flag: 0, + description: "Center ____ _ ____ _ ____ _ ____ _ ____ _ ____", + alignment: 65, + elementCount: 4, + patternLength: 50.8 + }, + CENTERTINY: { + type: "LTYPE", + pattern: [ + { + length: 4.7625, + shape: 0 + }, + { + length: -0.9525, + shape: 0 + }, + { + length: 0.9525, + shape: 0 + }, + { + length: -0.9525, + shape: 0 + } + ], + name: "CENTERTINY", + flag: 0, + description: "Center (.15x) ___ _ ___ _ ___ _ ___ _ ___ _ ___", + alignment: 65, + elementCount: 4, + patternLength: 7.619999999999999 + }, + CENTER2: { + type: "LTYPE", + pattern: [ + { + length: 19.05, + shape: 0 + }, + { + length: -3.175, + shape: 0 + }, + { + length: 3.175, + shape: 0 + }, + { + length: -3.175, + shape: 0 + } + ], + name: "CENTER2", + flag: 0, + description: "Center (.5x) ___ _ ___ _ ___ _ ___ _ ___ _ ___", + alignment: 65, + elementCount: 4, + patternLength: 28.575 + }, + CENTERX2: { + type: "LTYPE", + pattern: [ + { + length: 63.5, + shape: 0 + }, + { + length: -12.7, + shape: 0 + }, + { + length: 12.7, + shape: 0 + }, + { + length: -12.7, + shape: 0 + } + ], + name: "CENTERX2", + flag: 0, + description: "Center (2x) ________ __ ________ __ _____", + alignment: 65, + elementCount: 4, + patternLength: 101.6 + } + }) + }) +}) \ No newline at end of file