├── .babelrc ├── .gitignore ├── .jshintrc ├── LICENSE ├── README.md ├── commonjs └── package.json ├── jsconfig.json ├── package-lock.json ├── package.json ├── samples ├── browser │ └── index.html ├── data │ └── api-cw750-details.dxf └── node │ ├── parse-stream.js │ └── parse-sync.js ├── src ├── AutoCadColorIndex.ts ├── DxfArrayScanner.ts ├── DxfParser.ts ├── ParseHelpers.ts ├── entities │ ├── 3dface.ts │ ├── arc.ts │ ├── attdef.ts │ ├── circle.ts │ ├── dimension.ts │ ├── ellipse.ts │ ├── geomtry.ts │ ├── insert.ts │ ├── line.ts │ ├── lwpolyline.ts │ ├── mleader.ts │ ├── mtext.ts │ ├── point.ts │ ├── polyline.ts │ ├── solid.ts │ ├── spline.ts │ ├── text.ts │ └── vertex.ts └── index.ts ├── test ├── DxfArrayScanner.test.js ├── DxfParser.test.js └── data │ ├── arc1.approved.txt │ ├── arc1.dxf │ ├── arcs-as-splines.approved.txt │ ├── arcs-as-splines.dxf │ ├── blocks.approved.txt │ ├── blocks.dxf │ ├── blocks2.dxf │ ├── blocks2.expected.json │ ├── ellipse.dxf │ ├── ellipse.expected.json │ ├── extendeddata.dxf │ ├── extendeddata.expected.json │ ├── header.dxf │ ├── header.parser.out │ ├── header.scanner.out │ ├── layer-table.expected.json │ ├── ltype-table.expected.json │ ├── mleader.approved.txt │ ├── mleader.dxf │ ├── mtext-test.approved.txt │ ├── mtext-test.dxf │ ├── polylines.approved.txt │ ├── polylines.dxf │ ├── splines.dxf │ ├── splines.expected.json │ ├── tables.dxf │ └── viewport-table.expected.json ├── tsconfig.json └── webpack.config.js /.babelrc: -------------------------------------------------------------------------------- 1 | { 2 | "presets": ["@babel/preset-env"] 3 | } -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | node_modules/ 2 | .idea/ 3 | .settings/ 4 | private/ 5 | typings/ 6 | out.json 7 | *.log 8 | *.actual.json 9 | .vscode/ 10 | *.received.* 11 | commonjs/*.js 12 | esm/ 13 | *.tgz 14 | *.lock 15 | -------------------------------------------------------------------------------- /.jshintrc: -------------------------------------------------------------------------------- 1 | { 2 | "globals": { 3 | "process": true, 4 | "console": true, 5 | "require": true, 6 | "__filename": true, 7 | "__dirname": true, 8 | "module": true, 9 | "exports": true, 10 | "describe": true, 11 | "it": true, 12 | "setTimeout": true 13 | }, 14 | "strict": false 15 | } -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2015 GDS Storefront Estimating 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in 13 | all copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 21 | THE SOFTWARE. -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | 2 | # Dxf-Parser 3 | 4 | **Dxf Parser** is a javascript parser for dxf files. It reads dxf files into one large javascript object with readable properties and a more logical structure. 5 | 6 | Also, keep an eye on [three-dxf](https://github.com/gdsestimating/three-dxf), a browser module for rendering the output of Dxf-Parser in the browser. 7 | 8 | #### Install 9 | 10 | ```sh 11 | npm install dxf-parser 12 | ``` 13 | 14 | Browsers -- As of 0.1.3 standalone browserify version is in the commonjs/ folder. Copy it out of the install directory or just download it from the GitHub repo directly. We may evetually publish this to bower, but the build environment needs a little work first. 15 | 16 | #### Usage 17 | 18 | ``` js 19 | import DxfParser from 'dxf-parser'; 20 | 21 | // Grab fileText in node.js or browser 22 | const fileText = ...; 23 | 24 | const parser = new DxfParser(); 25 | try { 26 | const dxf = parser.parse(fileText); 27 | } catch(err) { 28 | return console.error(err.stack); 29 | } 30 | ``` 31 | 32 | See the [wiki Example Output page](https://github.com/gdsestimating/dxf-parser/wiki/Example-Output) to get an idea of what the results look like. 33 | 34 | #### Run Samples 35 | 36 | node.js 37 | 38 | ```sh 39 | npm install 40 | npm run build 41 | node samples/node/parseSync 42 | node samples/node/parseStream 43 | ``` 44 | 45 | browser - the [three-dxf repo](https://github.com/gdsestimating/three-dxf) has a sample for viewing dxf cad in the browser 46 | 47 | #### What's Supported 48 | 49 | Support 50 | 51 | * Header 52 | * Most 2D entities 53 | * Layers 54 | * LType table 55 | * Block table and inserts 56 | * VPort table 57 | * Text and some MTEXT 58 | * Some XData 59 | 60 | Does not yet support 61 | 62 | * 3DSolids 63 | * All types of Leaders 64 | * other less common objects and entities. 65 | 66 | ### Contributing 67 | 68 | See the [wiki](https://github.com/gdsestimating/dxf-parser/wiki) for info on contributing 69 | 70 | #### Run Tests 71 | 72 | ```sh 73 | npm install -g mocha 74 | //Then 75 | npm test 76 | //OR 77 | mocha test 78 | ``` 79 | -------------------------------------------------------------------------------- /commonjs/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "type": "commonjs" 3 | } 4 | -------------------------------------------------------------------------------- /jsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "target": "ES6", 4 | "module": "commonjs" 5 | } 6 | } -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "dxf-parser", 3 | "version": "1.1.2", 4 | "description": "Parse dxf files into a readable, logical js object.", 5 | "type": "module", 6 | "main": "./commonjs/index.js", 7 | "module": "./esm/index.js", 8 | "exports": { 9 | "import": "./esm/index.js", 10 | "require": "./commonjs/index.js" 11 | }, 12 | "types": "./esm/index.d.ts", 13 | "scripts": { 14 | "test": "mocha --require @babel/register test", 15 | "dev": "tsc -w & webpack --mode development", 16 | "prod": "tsc && webpack --mode production", 17 | "prepublishOnly": "npm run prod" 18 | }, 19 | "repository": { 20 | "type": "git", 21 | "url": "https://github.com/gdsestimating/dxf-parser.git" 22 | }, 23 | "bugs": { 24 | "url": "https://github.com/gdsestimating/dxf-parser/issues", 25 | "email": "bzuillsmith@gmail.com" 26 | }, 27 | "homepage": "https://github.com/gdsestimating/dxf-parser", 28 | "author": "GDS Storefront Estimating (gdsestimating.com)", 29 | "contributors": [ 30 | "Ben Zuill-Smith " 31 | ], 32 | "license": "MIT", 33 | "devDependencies": { 34 | "@babel/core": "^7.10.4", 35 | "@babel/preset-env": "^7.10.4", 36 | "@babel/register": "^7.10.4", 37 | "approvals": "^3.0.5", 38 | "mocha": "^8.0.1", 39 | "should": "^13.2.3", 40 | "typescript": "^4.4.3", 41 | "webpack": "^5.52.1", 42 | "webpack-cli": "^4.8.0" 43 | }, 44 | "dependencies": { 45 | "loglevel": "^1.7.1" 46 | }, 47 | "keywords": [ 48 | "dxf", 49 | "cad", 50 | "parser", 51 | "reader" 52 | ], 53 | "files": [ 54 | "commonjs", 55 | "esm", 56 | "src" 57 | ] 58 | } 59 | -------------------------------------------------------------------------------- /samples/browser/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | Dxf-Parser - Browser Sample 5 | 6 | 7 | 8 | 9 | 10 | 11 |
12 | 			
13 | 		
14 | 34 | 35 | -------------------------------------------------------------------------------- /samples/node/parse-stream.js: -------------------------------------------------------------------------------- 1 | import DxfParser from '../../esm/index.js' 2 | import fs from 'fs' 3 | import path from 'path' 4 | 5 | const __dirname = path.dirname(new URL(import.meta.url).pathname) 6 | 7 | var DXF_FILE_PATH = path.join(__dirname, '..', 'data', 'api-cw750-details.dxf'); 8 | var OUTPUT_FILE_NAME = "out.json"; 9 | 10 | var fileStream = fs.createReadStream(DXF_FILE_PATH, { encoding: 'utf8' }); 11 | 12 | var parser = new DxfParser(); 13 | const dxf = await parser.parseStream(fileStream); 14 | fs.writeFileSync(OUTPUT_FILE_NAME, JSON.stringify(dxf, null, 3)); 15 | console.log('Done writing output to ' + OUTPUT_FILE_NAME); 16 | -------------------------------------------------------------------------------- /samples/node/parse-sync.js: -------------------------------------------------------------------------------- 1 | import DxfParser from '../../esm/index.js' 2 | import fs from 'fs' 3 | import path from 'path' 4 | 5 | const __dirname = path.dirname(new URL(import.meta.url).pathname) 6 | 7 | var DXF_FILE_PATH = path.join(__dirname, '..', 'data', 'api-cw750-details.dxf'); 8 | var OUTPUT_FILE_NAME = "out.json"; 9 | 10 | var fileText = fs.readFileSync(DXF_FILE_PATH, 'utf8'); 11 | 12 | var parser = new DxfParser(); 13 | try { 14 | var dxf = parser.parseSync(fileText); 15 | fs.writeFileSync(OUTPUT_FILE_NAME, JSON.stringify(dxf, null, 3)); 16 | console.log('Done writing output to ' + OUTPUT_FILE_NAME); 17 | }catch(err) { 18 | console.error(err.stack); 19 | } 20 | -------------------------------------------------------------------------------- /src/AutoCadColorIndex.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * AutoCad files sometimes use an indexed color value between 1 and 255 inclusive. 3 | * Each value corresponds to a color. index 1 is red, that is 16711680 or 0xFF0000. 4 | * index 0 and 256, while included in this array, are actually reserved for inheritance 5 | * values in AutoCad so they should not be used for index color lookups. 6 | */ 7 | 8 | export default [ 9 | 0, 10 | 16711680, 11 | 16776960, 12 | 65280, 13 | 65535, 14 | 255, 15 | 16711935, 16 | 16777215, 17 | 8421504, 18 | 12632256, 19 | 16711680, 20 | 16744319, 21 | 13369344, 22 | 13395558, 23 | 10027008, 24 | 10046540, 25 | 8323072, 26 | 8339263, 27 | 4980736, 28 | 4990502, 29 | 16727808, 30 | 16752511, 31 | 13382400, 32 | 13401958, 33 | 10036736, 34 | 10051404, 35 | 8331008, 36 | 8343359, 37 | 4985600, 38 | 4992806, 39 | 16744192, 40 | 16760703, 41 | 13395456, 42 | 13408614, 43 | 10046464, 44 | 10056268, 45 | 8339200, 46 | 8347455, 47 | 4990464, 48 | 4995366, 49 | 16760576, 50 | 16768895, 51 | 13408512, 52 | 13415014, 53 | 10056192, 54 | 10061132, 55 | 8347392, 56 | 8351551, 57 | 4995328, 58 | 4997670, 59 | 16776960, 60 | 16777087, 61 | 13421568, 62 | 13421670, 63 | 10000384, 64 | 10000460, 65 | 8355584, 66 | 8355647, 67 | 5000192, 68 | 5000230, 69 | 12582656, 70 | 14679935, 71 | 10079232, 72 | 11717734, 73 | 7510016, 74 | 8755276, 75 | 6258432, 76 | 7307071, 77 | 3755008, 78 | 4344870, 79 | 8388352, 80 | 12582783, 81 | 6736896, 82 | 10079334, 83 | 5019648, 84 | 7510092, 85 | 4161280, 86 | 6258495, 87 | 2509824, 88 | 3755046, 89 | 4194048, 90 | 10485631, 91 | 3394560, 92 | 8375398, 93 | 2529280, 94 | 6264908, 95 | 2064128, 96 | 5209919, 97 | 1264640, 98 | 3099686, 99 | 65280, 100 | 8388479, 101 | 52224, 102 | 6736998, 103 | 38912, 104 | 5019724, 105 | 32512, 106 | 4161343, 107 | 19456, 108 | 2509862, 109 | 65343, 110 | 8388511, 111 | 52275, 112 | 6737023, 113 | 38950, 114 | 5019743, 115 | 32543, 116 | 4161359, 117 | 19475, 118 | 2509871, 119 | 65407, 120 | 8388543, 121 | 52326, 122 | 6737049, 123 | 38988, 124 | 5019762, 125 | 32575, 126 | 4161375, 127 | 19494, 128 | 2509881, 129 | 65471, 130 | 8388575, 131 | 52377, 132 | 6737074, 133 | 39026, 134 | 5019781, 135 | 32607, 136 | 4161391, 137 | 19513, 138 | 2509890, 139 | 65535, 140 | 8388607, 141 | 52428, 142 | 6737100, 143 | 39064, 144 | 5019800, 145 | 32639, 146 | 4161407, 147 | 19532, 148 | 2509900, 149 | 49151, 150 | 8380415, 151 | 39372, 152 | 6730444, 153 | 29336, 154 | 5014936, 155 | 24447, 156 | 4157311, 157 | 14668, 158 | 2507340, 159 | 32767, 160 | 8372223, 161 | 26316, 162 | 6724044, 163 | 19608, 164 | 5010072, 165 | 16255, 166 | 4153215, 167 | 9804, 168 | 2505036, 169 | 16383, 170 | 8364031, 171 | 13260, 172 | 6717388, 173 | 9880, 174 | 5005208, 175 | 8063, 176 | 4149119, 177 | 4940, 178 | 2502476, 179 | 255, 180 | 8355839, 181 | 204, 182 | 6710988, 183 | 152, 184 | 5000344, 185 | 127, 186 | 4145023, 187 | 76, 188 | 2500172, 189 | 4129023, 190 | 10452991, 191 | 3342540, 192 | 8349388, 193 | 2490520, 194 | 6245528, 195 | 2031743, 196 | 5193599, 197 | 1245260, 198 | 3089996, 199 | 8323327, 200 | 12550143, 201 | 6684876, 202 | 10053324, 203 | 4980888, 204 | 7490712, 205 | 4128895, 206 | 6242175, 207 | 2490444, 208 | 3745356, 209 | 12517631, 210 | 14647295, 211 | 10027212, 212 | 11691724, 213 | 7471256, 214 | 8735896, 215 | 6226047, 216 | 7290751, 217 | 3735628, 218 | 4335180, 219 | 16711935, 220 | 16744447, 221 | 13369548, 222 | 13395660, 223 | 9961624, 224 | 9981080, 225 | 8323199, 226 | 8339327, 227 | 4980812, 228 | 4990540, 229 | 16711871, 230 | 16744415, 231 | 13369497, 232 | 13395634, 233 | 9961586, 234 | 9981061, 235 | 8323167, 236 | 8339311, 237 | 4980793, 238 | 4990530, 239 | 16711807, 240 | 16744383, 241 | 13369446, 242 | 13395609, 243 | 9961548, 244 | 9981042, 245 | 8323135, 246 | 8339295, 247 | 4980774, 248 | 4990521, 249 | 16711743, 250 | 16744351, 251 | 13369395, 252 | 13395583, 253 | 9961510, 254 | 9981023, 255 | 8323103, 256 | 8339279, 257 | 4980755, 258 | 4990511, 259 | 3355443, 260 | 5987163, 261 | 8684676, 262 | 11382189, 263 | 14079702, 264 | 16777215 265 | ]; -------------------------------------------------------------------------------- /src/DxfArrayScanner.ts: -------------------------------------------------------------------------------- 1 | export interface IGroup { 2 | code: number; 3 | value: number | string | boolean; 4 | } 5 | 6 | /** 7 | * DxfArrayScanner 8 | * 9 | * Based off the AutoCad 2012 DXF Reference 10 | * http://images.autodesk.com/adsk/files/autocad_2012_pdf_dxf-reference_enu.pdf 11 | * 12 | * Reads through an array representing lines of a dxf file. Takes an array and 13 | * provides an easy interface to extract group code and value pairs. 14 | * @param data - an array where each element represents a line in the dxf file 15 | * @constructor 16 | */ 17 | export default class DxfArrayScanner { 18 | private _pointer = 0; 19 | private _eof = false; 20 | public lastReadGroup: IGroup; 21 | private _data: string[]; 22 | constructor(data: string[]) { 23 | this._data = data; 24 | } 25 | 26 | /** 27 | * Gets the next group (code, value) from the array. A group is two consecutive elements 28 | * in the array. The first is the code, the second is the value. 29 | * @returns {{code: Number}|*} 30 | */ 31 | public next() { 32 | if (!this.hasNext()) { 33 | if (!this._eof) 34 | throw new Error('Unexpected end of input: EOF group not read before end of file. Ended on code ' + this._data[this._pointer]); 35 | else 36 | throw new Error('Cannot call \'next\' after EOF group has been read'); 37 | } 38 | 39 | const group = { 40 | code: parseInt(this._data[this._pointer]) 41 | } as IGroup; 42 | 43 | this._pointer++; 44 | 45 | group.value = parseGroupValue(group.code, this._data[this._pointer].trim()); 46 | 47 | this._pointer++; 48 | 49 | if (group.code === 0 && group.value === 'EOF') this._eof = true; 50 | 51 | this.lastReadGroup = group; 52 | 53 | return group; 54 | } 55 | 56 | public peek() { 57 | if (!this.hasNext()) { 58 | if (!this._eof) 59 | throw new Error('Unexpected end of input: EOF group not read before end of file. Ended on code ' + this._data[this._pointer]); 60 | else 61 | throw new Error('Cannot call \'next\' after EOF group has been read'); 62 | } 63 | 64 | const group = { 65 | code: parseInt(this._data[this._pointer]) 66 | } as IGroup; 67 | 68 | group.value = parseGroupValue(group.code, this._data[this._pointer + 1].trim()); 69 | 70 | return group; 71 | } 72 | 73 | 74 | public rewind(numberOfGroups = 1) { 75 | this._pointer = this._pointer - numberOfGroups * 2; 76 | } 77 | 78 | /** 79 | * Returns true if there is another code/value pair (2 elements in the array). 80 | * @returns {boolean} 81 | */ 82 | public hasNext() { 83 | // Check if we have read EOF group code 84 | if (this._eof) { 85 | return false; 86 | } 87 | 88 | // We need to be sure there are two lines available 89 | if (this._pointer > this._data.length - 2) { 90 | return false; 91 | } 92 | return true; 93 | } 94 | 95 | /** 96 | * Returns true if the scanner is at the end of the array 97 | * @returns {boolean} 98 | */ 99 | public isEOF() { 100 | return this._eof; 101 | } 102 | } 103 | 104 | /** 105 | * Parse a value to its proper type. 106 | * See pages 3 - 10 of the AutoCad DXF 2012 reference given at the top of this file 107 | * 108 | * @param code 109 | * @param value 110 | * @returns {*} 111 | */ 112 | function parseGroupValue(code: number, value: string) { 113 | if (code <= 9) return value; 114 | if (code >= 10 && code <= 59) return parseFloat(value); 115 | if (code >= 60 && code <= 99) return parseInt(value); 116 | if (code >= 100 && code <= 109) return value; 117 | if (code >= 110 && code <= 149) return parseFloat(value); 118 | if (code >= 160 && code <= 179) return parseInt(value); 119 | if (code >= 210 && code <= 239) return parseFloat(value); 120 | if (code >= 270 && code <= 289) return parseInt(value); 121 | if (code >= 290 && code <= 299) return parseBoolean(value as '0' | '1'); 122 | if (code >= 300 && code <= 369) return value; 123 | if (code >= 370 && code <= 389) return parseInt(value); 124 | if (code >= 390 && code <= 399) return value; 125 | if (code >= 400 && code <= 409) return parseInt(value); 126 | if (code >= 410 && code <= 419) return value; 127 | if (code >= 420 && code <= 429) return parseInt(value); 128 | if (code >= 430 && code <= 439) return value; 129 | if (code >= 440 && code <= 459) return parseInt(value); 130 | if (code >= 460 && code <= 469) return parseFloat(value); 131 | if (code >= 470 && code <= 481) return value; 132 | if (code === 999) return value; 133 | if (code >= 1000 && code <= 1009) return value; 134 | if (code >= 1010 && code <= 1059) return parseFloat(value); 135 | if (code >= 1060 && code <= 1071) return parseInt(value); 136 | 137 | console.log('WARNING: Group code does not have a defined type: %j', { code: code, value: value }); 138 | return value; 139 | } 140 | 141 | /** 142 | * Parse a boolean according to a 1 or 0 value 143 | * @param str 144 | * @returns {boolean} 145 | */ 146 | function parseBoolean(str: '0' | '1') { 147 | if (str === '0') return false; 148 | if (str === '1') return true; 149 | throw TypeError('String \'' + str + '\' cannot be cast to Boolean type'); 150 | } -------------------------------------------------------------------------------- /src/ParseHelpers.ts: -------------------------------------------------------------------------------- 1 | import AUTO_CAD_COLOR_INDEX from './AutoCadColorIndex.js'; 2 | import DxfArrayScanner, { IGroup } from './DxfArrayScanner.js'; 3 | import { IEntity, IPoint } from './entities/geomtry.js'; 4 | 5 | /** 6 | * Returns the truecolor value of the given AutoCad color index value 7 | * @return {Number} truecolor value as a number 8 | */ 9 | export function getAcadColor(index: number) { 10 | return AUTO_CAD_COLOR_INDEX[index]; 11 | } 12 | 13 | /** 14 | * Parses the 2D or 3D coordinate, vector, or point. When complete, 15 | * the scanner remains on the last group of the coordinate. 16 | * @param {*} scanner 17 | */ 18 | export function parsePoint(scanner: DxfArrayScanner) { 19 | const point = {} as IPoint; 20 | 21 | // Reread group for the first coordinate 22 | scanner.rewind(); 23 | let curr = scanner.next(); 24 | 25 | let code = curr.code; 26 | point.x = curr.value as number; 27 | 28 | code += 10; 29 | curr = scanner.next(); 30 | if (curr.code != code) 31 | throw new Error('Expected code for point value to be ' + code + 32 | ' but got ' + curr.code + '.'); 33 | point.y = curr.value as number; 34 | 35 | code += 10; 36 | curr = scanner.next(); 37 | if (curr.code != code) { 38 | // Only the x and y are specified. Don't read z. 39 | scanner.rewind(); // Let the calling code advance off the point 40 | return point; 41 | } 42 | point.z = curr.value as number; 43 | 44 | return point; 45 | } 46 | 47 | 48 | /** 49 | * Parses 16 numbers as an array. When complete, 50 | * the scanner remains on the last group of the value. 51 | * @param {*} scanner 52 | * @param {*} groupCode 53 | */ 54 | export function parseMatrix(scanner: DxfArrayScanner, groupCode: number) { 55 | // Reread group for the first coordinate 56 | scanner.rewind(); 57 | const matrix: number[] = []; 58 | 59 | for (let i=0;i<16;i++) { 60 | const curr = scanner.next(); 61 | if (curr.code !== groupCode) { 62 | throw new Error('Expected code for matrix value to be ' + groupCode + 63 | ' but got ' + curr.code + '.'); 64 | } 65 | 66 | matrix.push(curr.value as number); 67 | } 68 | return matrix; 69 | } 70 | 71 | /** 72 | * Attempts to parse codes common to all entities. Returns true if the group 73 | * was handled by this function. 74 | * @param {*} entity - the entity currently being parsed 75 | * @param {*} curr - the current group being parsed 76 | */ 77 | export function checkCommonEntityProperties(entity: IEntity, curr:IGroup, scanner:DxfArrayScanner) { 78 | switch (curr.code) { 79 | case 0: 80 | entity.type = curr.value as string; 81 | break; 82 | case 5: 83 | entity.handle = curr.value as number; 84 | break; 85 | case 6: 86 | entity.lineType = curr.value as string; 87 | break; 88 | case 8: // Layer name 89 | entity.layer = curr.value as string; 90 | break; 91 | case 48: 92 | entity.lineTypeScale = curr.value as number; 93 | break; 94 | case 60: 95 | entity.visible = curr.value === 0; 96 | break; 97 | case 62: // Acad Index Color. 0 inherits ByBlock. 256 inherits ByLayer. Default is bylayer 98 | entity.colorIndex = curr.value as number; 99 | entity.color = getAcadColor(Math.abs(curr.value as number)); 100 | break; 101 | case 67: 102 | entity.inPaperSpace = curr.value !== 0; 103 | break; 104 | case 100: 105 | //ignore 106 | break; 107 | case 101: // Embedded Object in ACAD 2018. 108 | // See https://ezdxf.readthedocs.io/en/master/dxfinternals/dxftags.html#embedded-objects 109 | while (curr.code != 0) { 110 | curr = scanner.next(); 111 | } 112 | scanner.rewind(); 113 | break; 114 | case 330: 115 | entity.ownerHandle = curr.value as string; 116 | break; 117 | case 347: 118 | entity.materialObjectHandle = curr.value as number; 119 | break; 120 | case 370: 121 | //From https://www.woutware.com/Forum/Topic/955/lineweight?returnUrl=%2FForum%2FUserPosts%3FuserId%3D478262319 122 | // An integer representing 100th of mm, must be one of the following values: 123 | // 0, 5, 9, 13, 15, 18, 20, 25, 30, 35, 40, 50, 53, 60, 70, 80, 90, 100, 106, 120, 140, 158, 200, 211. 124 | // -3 = STANDARD, -2 = BYLAYER, -1 = BYBLOCK 125 | entity.lineweight = curr.value as 0| 5| 9| 13| 15| 18| 20| 25| 30| 35| 40| 50| 53| 60| 70| 80| 90| 100| 106| 120| 140| 158| 200| 211|-3|-2|-1; 126 | break; 127 | case 420: // TrueColor Color 128 | entity.color = curr.value as number; 129 | break; 130 | case 1000: 131 | entity.extendedData = entity.extendedData || {}; 132 | entity.extendedData.customStrings = entity.extendedData.customStrings || []; 133 | entity.extendedData.customStrings.push(curr.value as string); 134 | break; 135 | case 1001: 136 | entity.extendedData = entity.extendedData || {}; 137 | entity.extendedData.applicationName = curr.value as string; 138 | break; 139 | default: 140 | return false; 141 | } 142 | return true; 143 | } 144 | -------------------------------------------------------------------------------- /src/entities/3dface.ts: -------------------------------------------------------------------------------- 1 | import DxfArrayScanner, { IGroup } from '../DxfArrayScanner.js'; 2 | import * as helpers from '../ParseHelpers.js'; 3 | import IGeometry, { IEntity, IPoint } from './geomtry.js'; 4 | 5 | export interface I3DfaceEntity extends IEntity { 6 | shape: boolean; 7 | hasContinuousLinetypePattern: boolean; 8 | vertices: IPoint[]; 9 | } 10 | 11 | export default class ThreeDface implements IGeometry { 12 | public ForEntityName = '3DFACE' as const; 13 | public parseEntity(scanner: DxfArrayScanner, curr: IGroup) { 14 | const entity = { type: curr.value as string, vertices: [] as IPoint[] } as I3DfaceEntity; 15 | curr = scanner.next(); 16 | while (!scanner.isEOF()) { 17 | if (curr.code === 0) break; 18 | switch (curr.code) { 19 | case 70: // 1 = Closed shape, 128 = plinegen?, 0 = default 20 | entity.shape = (((curr.value as number) & 1) === 1); 21 | entity.hasContinuousLinetypePattern = (((curr.value as number) & 128) === 128); 22 | break; 23 | case 10: // X coordinate of point 24 | entity.vertices = parse3dFaceVertices(scanner, curr); 25 | curr = scanner.lastReadGroup; 26 | break; 27 | default: 28 | helpers.checkCommonEntityProperties(entity, curr, scanner); 29 | break; 30 | } 31 | curr = scanner.next(); 32 | } 33 | return entity; 34 | } 35 | } 36 | 37 | function parse3dFaceVertices(scanner:DxfArrayScanner, curr:IGroup) { 38 | var vertices = []; 39 | var vertexIsStarted = false; 40 | var vertexIsFinished = false; 41 | var verticesPer3dFace = 4; // there can be up to four vertices per face, although 3 is most used for TIN 42 | 43 | for (let i = 0; i <= verticesPer3dFace; i++) { 44 | var vertex = {} as IPoint; 45 | while (!scanner.isEOF()) { 46 | if (curr.code === 0 || vertexIsFinished) break; 47 | 48 | switch (curr.code) { 49 | case 10: // X0 50 | case 11: // X1 51 | case 12: // X2 52 | case 13: // X3 53 | if (vertexIsStarted) { 54 | vertexIsFinished = true; 55 | continue; 56 | } 57 | vertex.x = curr.value as number; 58 | vertexIsStarted = true; 59 | break; 60 | case 20: // Y 61 | case 21: 62 | case 22: 63 | case 23: 64 | vertex.y = curr.value as number; 65 | break; 66 | case 30: // Z 67 | case 31: 68 | case 32: 69 | case 33: 70 | vertex.z = curr.value as number; 71 | break; 72 | default: 73 | // it is possible to have entity codes after the vertices. 74 | // So if code is not accounted for return to entity parser where it might be accounted for 75 | return vertices; 76 | } 77 | curr = scanner.next(); 78 | } 79 | // See https://groups.google.com/forum/#!topic/comp.cad.autocad/9gn8s5O_w6E 80 | vertices.push(vertex); 81 | vertexIsStarted = false; 82 | vertexIsFinished = false; 83 | } 84 | scanner.rewind(); 85 | return vertices; 86 | }; 87 | -------------------------------------------------------------------------------- /src/entities/arc.ts: -------------------------------------------------------------------------------- 1 | import DxfArrayScanner, { IGroup } from '../DxfArrayScanner.js'; 2 | import * as helpers from '../ParseHelpers.js'; 3 | import IGeometry, { IEntity, IPoint } from './geomtry.js'; 4 | 5 | export interface IArcEntity extends IEntity { 6 | center: IPoint; 7 | radius: number; 8 | startAngle: number; 9 | endAngle: number; 10 | angleLength: number; 11 | extrusionDirectionX: number; 12 | extrusionDirectionY: number; 13 | extrusionDirectionZ: number; 14 | } 15 | 16 | export default class Arc implements IGeometry { 17 | public ForEntityName = 'ARC' as const; 18 | public parseEntity(scanner: DxfArrayScanner, curr: IGroup) { 19 | const entity = { type: curr.value } as IArcEntity; 20 | curr = scanner.next(); 21 | while (!scanner.isEOF()) { 22 | if (curr.code === 0) break; 23 | 24 | switch (curr.code) { 25 | case 10: // X coordinate of point 26 | entity.center = helpers.parsePoint(scanner); 27 | break; 28 | case 40: // radius 29 | entity.radius = curr.value as number; 30 | break; 31 | case 50: // start angle 32 | entity.startAngle = Math.PI / 180 * (curr.value as number); 33 | break; 34 | case 51: // end angle 35 | entity.endAngle = Math.PI / 180 * (curr.value as number); 36 | entity.angleLength = entity.endAngle - entity.startAngle; // angleLength is deprecated 37 | break; 38 | case 210: 39 | entity.extrusionDirectionX = curr.value as number; 40 | break; 41 | case 220: 42 | entity.extrusionDirectionY = curr.value as number; 43 | break; 44 | case 230: 45 | entity.extrusionDirectionZ = curr.value as number; 46 | break; 47 | default: // ignored attribute 48 | helpers.checkCommonEntityProperties(entity, curr, scanner); 49 | break; 50 | } 51 | curr = scanner.next(); 52 | } 53 | return entity; 54 | } 55 | } 56 | -------------------------------------------------------------------------------- /src/entities/attdef.ts: -------------------------------------------------------------------------------- 1 | import DxfArrayScanner, { IGroup } from '../DxfArrayScanner.js'; 2 | import * as helpers from '../ParseHelpers.js'; 3 | import IGeometry, { IEntity, IPoint } from './geomtry.js'; 4 | 5 | export interface IAttdefEntity extends IEntity { 6 | scale: number; 7 | textStyle: 'STANDARD' | string; 8 | text: string; 9 | tag: string; 10 | prompt: string; 11 | startPoint: IPoint; 12 | endPoint: IPoint; 13 | thickness: number; 14 | textHeight: number; 15 | rotation: number; 16 | obliqueAngle: number; 17 | invisible: boolean; 18 | constant: boolean; 19 | verificationRequired: boolean; 20 | preset: boolean; 21 | backwards: boolean; 22 | mirrored: boolean; 23 | horizontalJustification: number; 24 | fieldLength: number; 25 | verticalJustification: number; 26 | extrusionDirectionX: number; 27 | extrusionDirectionY: number; 28 | extrusionDirectionZ: number; 29 | } 30 | 31 | export default class Attdef implements IGeometry { 32 | public ForEntityName = 'ATTDEF' as const; 33 | public parseEntity(scanner: DxfArrayScanner, curr: IGroup) { 34 | var entity = { 35 | type: curr.value, 36 | scale: 1, 37 | textStyle: 'STANDARD' 38 | } as IAttdefEntity; 39 | curr = scanner.next(); 40 | while (!scanner.isEOF()) { 41 | if (curr.code === 0) { 42 | break; 43 | } 44 | switch (curr.code) { 45 | case 1: 46 | entity.text = curr.value as string; 47 | break; 48 | case 2: 49 | entity.tag = curr.value as string; 50 | break; 51 | case 3: 52 | entity.prompt = curr.value as string; 53 | break; 54 | case 7: 55 | entity.textStyle = curr.value as string; 56 | break; 57 | case 10: // X coordinate of 'first alignment point' 58 | entity.startPoint = helpers.parsePoint(scanner); 59 | break; 60 | case 11: // X coordinate of 'second alignment point' 61 | entity.endPoint = helpers.parsePoint(scanner); 62 | break; 63 | case 39: 64 | entity.thickness = curr.value as number; 65 | break; 66 | case 40: 67 | entity.textHeight = curr.value as number; 68 | break; 69 | case 41: 70 | entity.scale = curr.value as number; 71 | break; 72 | case 50: 73 | entity.rotation = curr.value as number; 74 | break; 75 | case 51: 76 | entity.obliqueAngle = curr.value as number; 77 | break; 78 | case 70: 79 | entity.invisible = !!((curr.value as number) & 0x01); 80 | entity.constant = !!((curr.value as number) & 0x02); 81 | entity.verificationRequired = !!((curr.value as number) & 0x04); 82 | entity.preset = !!((curr.value as number) & 0x08); 83 | break; 84 | case 71: 85 | entity.backwards = !!((curr.value as number) & 0x02); 86 | entity.mirrored = !!((curr.value as number) & 0x04); 87 | break; 88 | case 72: 89 | // TODO: enum values? 90 | entity.horizontalJustification = curr.value as number; 91 | break; 92 | case 73: 93 | entity.fieldLength = curr.value as number; 94 | break; 95 | case 74: 96 | // TODO: enum values? 97 | entity.verticalJustification = curr.value as number; 98 | break; 99 | case 100: 100 | break; 101 | case 210: 102 | entity.extrusionDirectionX = curr.value as number; 103 | break; 104 | case 220: 105 | entity.extrusionDirectionY = curr.value as number; 106 | break; 107 | case 230: 108 | entity.extrusionDirectionZ = curr.value as number; 109 | break; 110 | default: 111 | helpers.checkCommonEntityProperties(entity, curr, scanner); 112 | break; 113 | } 114 | curr = scanner.next(); 115 | } 116 | 117 | return entity; 118 | } 119 | } 120 | -------------------------------------------------------------------------------- /src/entities/circle.ts: -------------------------------------------------------------------------------- 1 | import DxfArrayScanner, { IGroup } from '../DxfArrayScanner.js'; 2 | import * as helpers from '../ParseHelpers.js'; 3 | import IGeometry, { IEntity, IPoint } from './geomtry.js'; 4 | 5 | export interface ICircleEntity extends IEntity { 6 | center: IPoint; 7 | radius: number; 8 | startAngle: number; 9 | endAngle: number; 10 | angleLength: number; 11 | } 12 | 13 | export default class Circle implements IGeometry { 14 | public ForEntityName = 'CIRCLE' as const; 15 | public parseEntity(scanner: DxfArrayScanner, curr: IGroup) { 16 | const entity = { type: curr.value } as ICircleEntity; 17 | curr = scanner.next(); 18 | while (!scanner.isEOF()) { 19 | if (curr.code === 0) break; 20 | 21 | switch (curr.code) { 22 | case 10: // X coordinate of point 23 | entity.center = helpers.parsePoint(scanner); 24 | break; 25 | case 40: // radius 26 | entity.radius = (curr.value as number); 27 | break; 28 | case 50: // start angle 29 | entity.startAngle = Math.PI / 180 * (curr.value as number); 30 | break; 31 | case 51: // end angle 32 | const endAngle = Math.PI / 180 * (curr.value as number); 33 | if (endAngle < entity.startAngle) 34 | entity.angleLength = endAngle + 2 * Math.PI - entity.startAngle; 35 | else 36 | entity.angleLength = endAngle - entity.startAngle; 37 | entity.endAngle = endAngle; 38 | break; 39 | default: // ignored attribute 40 | helpers.checkCommonEntityProperties(entity, curr, scanner); 41 | break; 42 | } 43 | curr = scanner.next(); 44 | } 45 | return entity; 46 | } 47 | } 48 | -------------------------------------------------------------------------------- /src/entities/dimension.ts: -------------------------------------------------------------------------------- 1 | import DxfArrayScanner, { IGroup } from '../DxfArrayScanner.js'; 2 | import * as helpers from '../ParseHelpers.js'; 3 | import IGeometry, { IEntity, IPoint } from './geomtry.js'; 4 | 5 | export interface IDimensionEntity extends IEntity{ 6 | block: string; 7 | anchorPoint: IPoint; 8 | middleOfText: IPoint; 9 | insertionPoint: IPoint; 10 | linearOrAngularPoint1: IPoint; 11 | linearOrAngularPoint2: IPoint; 12 | diameterOrRadiusPoint: IPoint; 13 | arcPoint: IPoint; 14 | dimensionType: number; 15 | attachmentPoint: number; 16 | actualMeasurement: number; 17 | text: string; 18 | angle: number; 19 | } 20 | 21 | export default class Dimension implements IGeometry { 22 | public ForEntityName = 'DIMENSION' as const; 23 | public parseEntity(scanner: DxfArrayScanner, curr: IGroup) { 24 | const entity = { type: curr.value } as IDimensionEntity; 25 | curr = scanner.next(); 26 | while(!scanner.isEOF()) { 27 | if(curr.code === 0) break; 28 | 29 | switch(curr.code) { 30 | case 2: // Referenced block name 31 | entity.block = curr.value as string; 32 | break; 33 | case 10: // X coordinate of 'first alignment point' 34 | entity.anchorPoint = helpers.parsePoint(scanner); 35 | break; 36 | case 11: 37 | entity.middleOfText = helpers.parsePoint(scanner); 38 | break; 39 | case 12: // Insertion point for clones of a dimension 40 | entity.insertionPoint = helpers.parsePoint(scanner); 41 | break; 42 | case 13: // Definition point for linear and angular dimensions 43 | entity.linearOrAngularPoint1 = helpers.parsePoint(scanner); 44 | break; 45 | case 14: // Definition point for linear and angular dimensions 46 | entity.linearOrAngularPoint2 = helpers.parsePoint(scanner); 47 | break; 48 | case 15: // Definition point for diameter, radius, and angular dimensions 49 | entity.diameterOrRadiusPoint = helpers.parsePoint(scanner); 50 | break; 51 | case 16: // Point defining dimension arc for angular dimensions 52 | entity.arcPoint = helpers.parsePoint(scanner); 53 | break; 54 | case 70: // Dimension type 55 | entity.dimensionType = curr.value as number; 56 | break; 57 | case 71: // 5 = Middle center 58 | entity.attachmentPoint = curr.value as number; 59 | break; 60 | case 42: // Actual measurement 61 | entity.actualMeasurement = curr.value as number; 62 | break; 63 | case 1: // Text entered by user explicitly 64 | entity.text = curr.value as string; 65 | break; 66 | case 50: // Angle of rotated, horizontal, or vertical dimensions 67 | entity.angle = curr.value as number; 68 | break; 69 | default: // check common entity attributes 70 | helpers.checkCommonEntityProperties(entity, curr, scanner); 71 | break; 72 | } 73 | curr = scanner.next(); 74 | } 75 | 76 | return entity; 77 | } 78 | } 79 | -------------------------------------------------------------------------------- /src/entities/ellipse.ts: -------------------------------------------------------------------------------- 1 | import DxfArrayScanner, { IGroup } from '../DxfArrayScanner.js'; 2 | import * as helpers from '../ParseHelpers.js'; 3 | import IGeometry, { IEntity, IPoint } from './geomtry.js'; 4 | 5 | export interface IEllipseEntity extends IEntity { 6 | center: IPoint; 7 | majorAxisEndPoint: IPoint; 8 | axisRatio: number; 9 | startAngle: number; 10 | endAngle: number; 11 | name: string; 12 | } 13 | 14 | export default class Ellipse implements IGeometry { 15 | public ForEntityName = 'ELLIPSE' as const; 16 | public parseEntity(scanner: DxfArrayScanner, curr: IGroup) { 17 | const entity = { type: curr.value } as IEllipseEntity; 18 | curr = scanner.next(); 19 | while (!scanner.isEOF()) { 20 | if (curr.code === 0) break; 21 | 22 | switch (curr.code) { 23 | case 10: 24 | entity.center = helpers.parsePoint(scanner); 25 | break; 26 | case 11: 27 | entity.majorAxisEndPoint = helpers.parsePoint(scanner); 28 | break; 29 | case 40: 30 | entity.axisRatio = curr.value as number; 31 | break; 32 | case 41: 33 | entity.startAngle = curr.value as number; 34 | break; 35 | case 42: 36 | entity.endAngle = curr.value as number; 37 | break; 38 | case 2: 39 | entity.name = curr.value as string; 40 | break; 41 | default: // check common entity attributes 42 | helpers.checkCommonEntityProperties(entity, curr, scanner); 43 | break; 44 | } 45 | 46 | curr = scanner.next(); 47 | } 48 | 49 | return entity; 50 | } 51 | } 52 | -------------------------------------------------------------------------------- /src/entities/geomtry.ts: -------------------------------------------------------------------------------- 1 | import DxfArrayScanner, { IGroup } from "../DxfArrayScanner.js"; 2 | 3 | export interface IPoint { 4 | x: number; 5 | y: number; 6 | z: number; 7 | } 8 | 9 | export interface IEntity { 10 | lineType: string; 11 | layer: string; 12 | lineTypeScale: number; 13 | visible: boolean; 14 | colorIndex: number; 15 | color: number; 16 | inPaperSpace: boolean; 17 | ownerHandle: string; 18 | materialObjectHandle: number; 19 | lineweight: 0| 5| 9| 13| 15| 18| 20| 25| 30| 35| 40| 50| 53| 60| 70| 80| 90| 100| 106| 120| 140| 158| 200| 211|-3|-2|-1; 20 | extendedData: { 21 | customStrings: string[]; 22 | applicationName: string; 23 | }; 24 | type: string; 25 | handle: number; 26 | } 27 | 28 | export type EntityName = 'POINT' 29 | | '3DFACE' 30 | | 'ARC' 31 | | 'ATTDEF' 32 | | 'CIRCLE' 33 | | 'DIMENSION' 34 | | 'MULTILEADER' 35 | | 'ELLIPSE' 36 | | 'INSERT' 37 | | 'LINE' 38 | | 'LWPOLYLINE' 39 | | 'MTEXT' 40 | | 'POLYLINE' 41 | | 'SOLID' 42 | | 'SPLINE' 43 | | 'TEXT' 44 | | 'VERTEX'; 45 | 46 | export default interface IGeometry { 47 | ForEntityName: EntityName; 48 | parseEntity(scanner: DxfArrayScanner, curr: IGroup): IEntity; 49 | } 50 | -------------------------------------------------------------------------------- /src/entities/insert.ts: -------------------------------------------------------------------------------- 1 | import DxfArrayScanner, { IGroup } from '../DxfArrayScanner.js'; 2 | import * as helpers from '../ParseHelpers.js'; 3 | import IGeometry, { IEntity, IPoint } from './geomtry.js'; 4 | 5 | export interface IInsertEntity extends IEntity { 6 | name: string; 7 | xScale: number; 8 | yScale: number; 9 | zScale: number; 10 | position: IPoint; 11 | rotation: number; 12 | columnCount: number; 13 | rowCount: number; 14 | columnSpacing: number; 15 | rowSpacing: number; 16 | extrusionDirection: IPoint; 17 | } 18 | 19 | export default class Insert implements IGeometry { 20 | public ForEntityName = 'INSERT' as const; 21 | public parseEntity(scanner: DxfArrayScanner, curr: IGroup) { 22 | const entity = { type: curr.value } as IInsertEntity; 23 | curr = scanner.next(); 24 | while (!scanner.isEOF()) { 25 | if (curr.code === 0) break; 26 | 27 | switch (curr.code) { 28 | case 2: 29 | entity.name = curr.value as string; 30 | break; 31 | case 41: 32 | entity.xScale = curr.value as number; 33 | break; 34 | case 42: 35 | entity.yScale = curr.value as number; 36 | break; 37 | case 43: 38 | entity.zScale = curr.value as number; 39 | break; 40 | case 10: 41 | entity.position = helpers.parsePoint(scanner); 42 | break; 43 | case 50: 44 | entity.rotation = curr.value as number; 45 | break; 46 | case 70: 47 | entity.columnCount = curr.value as number; 48 | break; 49 | case 71: 50 | entity.rowCount = curr.value as number; 51 | break; 52 | case 44: 53 | entity.columnSpacing = curr.value as number; 54 | break; 55 | case 45: 56 | entity.rowSpacing = curr.value as number; 57 | break; 58 | case 210: 59 | entity.extrusionDirection = helpers.parsePoint(scanner); 60 | break; 61 | default: // check common entity attributes 62 | helpers.checkCommonEntityProperties(entity, curr, scanner); 63 | break; 64 | } 65 | curr = scanner.next(); 66 | } 67 | 68 | return entity; 69 | } 70 | } 71 | -------------------------------------------------------------------------------- /src/entities/line.ts: -------------------------------------------------------------------------------- 1 | import DxfArrayScanner, { IGroup } from '../DxfArrayScanner.js'; 2 | import * as helpers from '../ParseHelpers.js'; 3 | import IGeometry, { IEntity, IPoint } from './geomtry.js'; 4 | 5 | export interface ILineEntity extends IEntity{ 6 | vertices: IPoint[]; 7 | extrusionDirection: IPoint; 8 | } 9 | 10 | export default class Line implements IGeometry{ 11 | public ForEntityName= 'LINE' as const; 12 | public parseEntity(scanner: DxfArrayScanner, curr: IGroup) { 13 | const entity = { type: curr.value, vertices: [] as IPoint[] } as ILineEntity; 14 | curr = scanner.next(); 15 | while(!scanner.isEOF()) { 16 | if(curr.code === 0) break; 17 | 18 | switch(curr.code) { 19 | case 10: // X coordinate of point 20 | entity.vertices.unshift(helpers.parsePoint(scanner)); 21 | break; 22 | case 11: 23 | entity.vertices.push(helpers.parsePoint(scanner)); 24 | break; 25 | case 210: 26 | entity.extrusionDirection = helpers.parsePoint(scanner); 27 | break; 28 | case 100: 29 | break; 30 | default: 31 | helpers.checkCommonEntityProperties(entity, curr, scanner); 32 | break; 33 | } 34 | 35 | curr = scanner.next(); 36 | } 37 | return entity; 38 | } 39 | } 40 | -------------------------------------------------------------------------------- /src/entities/lwpolyline.ts: -------------------------------------------------------------------------------- 1 | import DxfArrayScanner, { IGroup } from '../DxfArrayScanner.js'; 2 | import * as helpers from '../ParseHelpers.js'; 3 | import IGeometry, { IEntity, IPoint } from './geomtry.js'; 4 | 5 | export interface IVertex extends IPoint{ 6 | startWidth: number; 7 | endWidth: number; 8 | bulge: number; 9 | } 10 | 11 | export interface ILwpolylineEntity extends IEntity { 12 | vertices: IVertex[]; 13 | elevation: number; 14 | depth: number; 15 | shape: boolean; 16 | hasContinuousLinetypePattern: boolean; 17 | width: number; 18 | extrusionDirectionX: number; 19 | extrusionDirectionY: number; 20 | extrusionDirectionZ: number; 21 | } 22 | 23 | export default class Lwpolyline implements IGeometry { 24 | public ForEntityName = 'LWPOLYLINE' as const; 25 | public parseEntity(scanner: DxfArrayScanner, curr: IGroup) { 26 | const entity = { type: curr.value, vertices: [] as IVertex[] } as ILwpolylineEntity; 27 | let numberOfVertices = 0; 28 | curr = scanner.next(); 29 | while (!scanner.isEOF()) { 30 | if (curr.code === 0) break; 31 | 32 | switch (curr.code) { 33 | case 38: 34 | entity.elevation = curr.value as number; 35 | break; 36 | case 39: 37 | entity.depth = curr.value as number; 38 | break; 39 | case 70: // 1 = Closed shape, 128 = plinegen?, 0 = default 40 | entity.shape = (((curr.value as number) & 1) === 1); 41 | entity.hasContinuousLinetypePattern = (((curr.value as number) & 128) === 128); 42 | break; 43 | case 90: 44 | numberOfVertices = curr.value as number; 45 | break; 46 | case 10: // X coordinate of point 47 | entity.vertices = parseLWPolylineVertices(numberOfVertices, scanner); 48 | break; 49 | case 43: 50 | if (curr.value !== 0) entity.width = curr.value as number; 51 | break; 52 | case 210: 53 | entity.extrusionDirectionX = curr.value as number; 54 | break; 55 | case 220: 56 | entity.extrusionDirectionY = curr.value as number; 57 | break; 58 | case 230: 59 | entity.extrusionDirectionZ = curr.value as number; 60 | break; 61 | default: 62 | helpers.checkCommonEntityProperties(entity, curr, scanner); 63 | break; 64 | } 65 | curr = scanner.next(); 66 | } 67 | return entity; 68 | } 69 | } 70 | 71 | function parseLWPolylineVertices(n:number, scanner: DxfArrayScanner) { 72 | if (!n || n <= 0) throw Error('n must be greater than 0 verticies'); 73 | const vertices = [] as IVertex[]; 74 | let vertexIsStarted = false; 75 | let vertexIsFinished = false; 76 | let curr = scanner.lastReadGroup; 77 | 78 | for (let i = 0; i < n; i++) { 79 | const vertex = {} as IVertex; 80 | while (!scanner.isEOF()) { 81 | if (curr.code === 0 || vertexIsFinished) break; 82 | 83 | switch (curr.code) { 84 | case 10: // X 85 | if (vertexIsStarted) { 86 | vertexIsFinished = true; 87 | continue; 88 | } 89 | vertex.x = curr.value as number; 90 | vertexIsStarted = true; 91 | break; 92 | case 20: // Y 93 | vertex.y = curr.value as number; 94 | break; 95 | case 30: // Z 96 | vertex.z = curr.value as number; 97 | break; 98 | case 40: // start width 99 | vertex.startWidth = curr.value as number; 100 | break; 101 | case 41: // end width 102 | vertex.endWidth = curr.value as number; 103 | break; 104 | case 42: // bulge 105 | if (curr.value != 0) vertex.bulge = curr.value as number; 106 | break; 107 | default: 108 | // if we do not hit known code return vertices. Code might belong to entity 109 | scanner.rewind(); 110 | if (vertexIsStarted) { 111 | vertices.push(vertex); 112 | } 113 | scanner.rewind(); 114 | return vertices; 115 | } 116 | curr = scanner.next(); 117 | } 118 | // See https://groups.google.com/forum/#!topic/comp.cad.autocad/9gn8s5O_w6E 119 | vertices.push(vertex); 120 | vertexIsStarted = false; 121 | vertexIsFinished = false; 122 | } 123 | scanner.rewind(); 124 | return vertices; 125 | } 126 | -------------------------------------------------------------------------------- /src/entities/mleader.ts: -------------------------------------------------------------------------------- 1 | import DxfArrayScanner, { IGroup } from "../DxfArrayScanner.js"; 2 | import * as helpers from "../ParseHelpers.js"; 3 | import IGeometry, { IEntity, IPoint } from "./geomtry.js"; 4 | 5 | // Helpful doc at https://atlight.github.io/formats/dxf-leader.html 6 | // Codes at https://images.autodesk.com/adsk/files/autocad_2012_pdf_dxf-reference_enu.pdf 7 | 8 | export interface ILeaderEntity extends IEntity { 9 | leaderStyleId: number; // 340 10 | // propertyOverrideFlag // 90 11 | leaderLineType: number; // 170 12 | leaderLineColor: number; // 91 13 | leaderLineTypeId: number; // 341 14 | leaderLineWeight: number; // 171 15 | enableLanding: boolean; // 290 16 | enableDogLeg: boolean; // 291 17 | doglegLength: number; // 41 18 | arrowHeadId: number; // 342 19 | arrowHeadSize: number; // 42 20 | contentType: number; // 172 21 | textStyleId: number; // 343 22 | textLeftAttachmentType: number; // 173 23 | textRightAttachmentType: number; // 95 24 | textAngleType: number; // 174 25 | textAlignmentType: number; // 175 26 | textColor: number; // 92 27 | enableFrameText: boolean; // 292 28 | blockContentId: number; // 344 29 | blockContentColor: number; // 93 30 | blockContentScale: IPoint; // 10 31 | blockContentRotation: number; // 43 32 | blockContentConnectionType: number; // 176 33 | enableAnotationScale: boolean; // 293 34 | arrowHeadIndex: number; // 94 35 | //arrowHeadId: number; // 345 - duplicate key in spec doc 36 | blockAttributeId: number; // 330 37 | blockAttributeIndex: number; // 177 38 | blockAttributeWidth: number; // 44 39 | blockAttributeTextString: string; // 302 40 | textDirectionNegative: boolean; // 294 41 | textAlignInIPE: number; // 178 42 | textAttachmentPoint: number; // 179 43 | textAttachmentDirectionMText: number; // 271 44 | textAttachmentDirectionBottom: number; // 272 45 | textAttachmentDirectionTop: number; // 273 46 | 47 | contextData: IMLeaderContextData; // 300 48 | } 49 | 50 | interface IMLeaderContextData { 51 | contentScale: number; // 40 52 | contentBasePosition: IPoint; // 10,20,30 53 | textHeight: number; // 41 54 | arrowHeadSize: number; // 140 55 | landingGap: number; // 145 56 | hasMText: boolean; // 290 57 | defaultTextContents: string; // 304 58 | textNormalDirection: IPoint; // 11,21,31 59 | textLocation: IPoint; // 12,22,32 60 | textDirection: IPoint; // 13,23,33 61 | textRotation: number; // 42 62 | textWidth: number; // 43 63 | // textHeight: number; // 44 - duplicate key in spec doc 64 | textLineSpacingFactor: number; // 45 65 | textLineSpacingStyle: number; // 170 66 | textColor: number; // 90 67 | textAttachment: number; // 171 68 | textFlowDirection: number; // 172 69 | textBackgroundColor: number; // 91 70 | textBackgroundScaleFactor: number; // 141 71 | textBackgroundTransparency: number; // 92 72 | textBackgroundColorOn: boolean; // 291 73 | textBackgroundFillOn: boolean; // 292 74 | textColumnType: number; // 173 75 | textUseAutoHeight: boolean; // 293 76 | textColumnWidth: number; // 142 77 | textColumnGutterWidth: number; // 143 78 | textColumnFlowReversed: boolean; // 294 79 | textColumnHeight: number; // 144 80 | textUseWordBreak: boolean; // 295 81 | hasBlock: boolean; // 296 82 | blockContentId: number; // 341 83 | blockContentNormalDirection: IPoint; // 14,24,34 84 | blockContentPosition: IPoint; // 15,25,35 85 | blockContentScale: number; // 16 86 | blockContentRotation: number; // 46 87 | blockContentColor: number; // 93 88 | blockTransformationMatrix: number[]; // 47 89 | planeOriginPoint: IPoint; // 110 (120,130) 90 | planeXAxisDirection: IPoint; // 111 (121,131) 91 | planeYAxisDirection: IPoint; // 112 (122,132) 92 | planeNormalReversed: boolean; // 297 93 | 94 | leaders: IMLeaderLeader[]; // 302 95 | } 96 | 97 | interface IMLeaderLeader { 98 | hasSetLastLeaderLinePoint: boolean; // 290 99 | hasSetDoglegVector: boolean; // 291 100 | lastLeaderLinePoint: IPoint; // 10,20,30 101 | doglegVector: IPoint; // 11,21,31 102 | // breakStartPoint // 12,22,32 103 | // breakEndPoint // 13,23,33 104 | leaderBranchIndex: number; // 90 105 | doglegLength: number; // 40 106 | 107 | leaderLines: IMLeaderLine[]; // 303 108 | } 109 | 110 | interface IMLeaderLine { 111 | vertices: IPoint[][]; // 10,20,30 112 | // breakPointIndex // 90, 113 | // breakStartPoint // 11,21,33 114 | // breakEndPoint // 12,22,32 115 | leaderLineIndex: number; // 91 116 | } 117 | 118 | export default class MLeader implements IGeometry { 119 | public ForEntityName = "MULTILEADER" as const; 120 | 121 | public parseEntity(scanner: DxfArrayScanner, curr: IGroup) { 122 | const entity = { type: curr.value } as ILeaderEntity; 123 | entity.contextData = { 124 | leaders: [], 125 | } as any; 126 | 127 | curr = scanner.next(); 128 | 129 | function parseCommonData() { 130 | while (!scanner.isEOF()) { 131 | switch (curr.code) { 132 | case 0: // END 133 | return; 134 | case 340: 135 | entity.leaderStyleId = curr.value as number; 136 | break; 137 | case 170: 138 | entity.leaderLineType = curr.value as number; 139 | break; 140 | case 91: 141 | entity.leaderLineColor = curr.value as number; 142 | break; 143 | case 341: 144 | entity.leaderLineTypeId = curr.value as number; 145 | break; 146 | case 171: 147 | entity.leaderLineWeight = curr.value as number; 148 | break; 149 | case 41: 150 | entity.doglegLength = curr.value as number; 151 | break; 152 | case 290: 153 | entity.enableLanding = curr.value as boolean; 154 | break; 155 | case 291: 156 | entity.enableDogLeg = curr.value as boolean; 157 | break; 158 | case 342: 159 | entity.arrowHeadId = curr.value as number; 160 | break; 161 | case 42: 162 | entity.arrowHeadSize = curr.value as number; 163 | break; 164 | case 172: 165 | entity.contentType = curr.value as number; 166 | break; 167 | case 173: 168 | entity.textLeftAttachmentType = curr.value as number; 169 | break; 170 | case 95: 171 | entity.textLeftAttachmentType = curr.value as number; 172 | break; 173 | case 174: 174 | entity.textAngleType = curr.value as number; 175 | break; 176 | case 175: 177 | entity.textAlignmentType = curr.value as number; 178 | break; 179 | case 343: 180 | entity.textStyleId = curr.value as number; 181 | break; 182 | case 92: 183 | entity.textColor = curr.value as number; 184 | break; 185 | case 292: 186 | entity.enableFrameText = curr.value as boolean; 187 | break; 188 | case 344: 189 | entity.blockContentId = curr.value as number; 190 | break; 191 | case 93: 192 | entity.blockContentColor = curr.value as number; 193 | break; 194 | case 10: 195 | entity.blockContentScale = helpers.parsePoint(scanner); 196 | break; 197 | case 43: 198 | entity.blockContentRotation = curr.value as number; 199 | break; 200 | case 176: 201 | entity.blockContentConnectionType = 202 | curr.value as number; 203 | break; 204 | case 293: 205 | entity.enableAnotationScale = curr.value as boolean; 206 | break; 207 | case 94: 208 | entity.arrowHeadIndex = curr.value as number; 209 | break; 210 | case 330: 211 | entity.blockAttributeId = curr.value as number; 212 | break; 213 | case 177: 214 | entity.blockAttributeIndex = curr.value as number; 215 | break; 216 | case 44: 217 | entity.blockAttributeWidth = curr.value as number; 218 | break; 219 | case 302: 220 | entity.blockAttributeTextString = curr.value as string; 221 | break; 222 | case 294: 223 | entity.textDirectionNegative = curr.value as boolean; 224 | break; 225 | case 178: 226 | entity.textAlignInIPE = curr.value as number; 227 | break; 228 | case 179: 229 | entity.textAttachmentPoint = curr.value as number; 230 | break; 231 | case 271: 232 | entity.textAttachmentDirectionMText = 233 | curr.value as number; 234 | break; 235 | case 272: 236 | entity.textAttachmentDirectionBottom = 237 | curr.value as number; 238 | break; 239 | case 273: 240 | entity.textAttachmentDirectionTop = 241 | curr.value as number; 242 | break; 243 | 244 | case 300: // START CONTEXT_DATA 245 | parseContextData(); 246 | break; 247 | default: 248 | helpers.checkCommonEntityProperties( 249 | entity, 250 | curr, 251 | scanner 252 | ); 253 | break; 254 | } 255 | curr = scanner.next(); 256 | } 257 | } 258 | 259 | function parseContextData() { 260 | while (!scanner.isEOF()) { 261 | switch (curr.code) { 262 | case 40: 263 | entity.contextData.contentScale = curr.value as number; 264 | break; 265 | case 10: 266 | entity.contextData.contentBasePosition = 267 | helpers.parsePoint(scanner); 268 | break; 269 | case 145: 270 | entity.contextData.landingGap = curr.value as number; 271 | break; 272 | case 290: 273 | entity.contextData.hasMText = curr.value as boolean; 274 | break; 275 | case 304: 276 | entity.contextData.defaultTextContents = 277 | curr.value as string; 278 | break; 279 | case 11: 280 | entity.contextData.textNormalDirection = 281 | helpers.parsePoint(scanner); 282 | break; 283 | case 12: 284 | entity.contextData.textLocation = 285 | helpers.parsePoint(scanner); 286 | break; 287 | case 13: 288 | entity.contextData.textDirection = 289 | helpers.parsePoint(scanner); 290 | break; 291 | case 140: 292 | entity.contextData.arrowHeadSize = curr.value as number; 293 | break; 294 | case 41: 295 | entity.contextData.textHeight = curr.value as number; 296 | break; 297 | case 42: 298 | entity.contextData.textRotation = curr.value as number; 299 | break; 300 | case 43: 301 | entity.contextData.textWidth = curr.value as number; 302 | break; 303 | case 44: 304 | entity.contextData.textHeight = curr.value as number; 305 | break; 306 | case 45: 307 | entity.contextData.textLineSpacingFactor = 308 | curr.value as number; 309 | break; 310 | case 90: 311 | entity.contextData.textColor = curr.value as number; 312 | break; 313 | case 170: 314 | entity.contextData.textLineSpacingStyle = 315 | curr.value as number; 316 | break; 317 | case 171: 318 | entity.contextData.textAttachment = 319 | curr.value as number; 320 | break; 321 | case 172: 322 | entity.contextData.textFlowDirection = 323 | curr.value as number; 324 | break; 325 | case 141: 326 | entity.contextData.textBackgroundScaleFactor = 327 | curr.value as number; 328 | break; 329 | case 92: 330 | entity.contextData.textBackgroundTransparency = 331 | curr.value as number; 332 | break; 333 | case 291: 334 | entity.contextData.textBackgroundColorOn = 335 | curr.value as boolean; 336 | break; 337 | case 292: 338 | entity.contextData.textBackgroundFillOn = 339 | curr.value as boolean; 340 | break; 341 | case 293: 342 | entity.contextData.textUseAutoHeight = 343 | curr.value as boolean; 344 | break; 345 | case 173: 346 | entity.contextData.textColumnType = 347 | curr.value as number; 348 | break; 349 | case 142: 350 | entity.contextData.textColumnWidth = 351 | curr.value as number; 352 | break; 353 | case 143: 354 | entity.contextData.textColumnGutterWidth = 355 | curr.value as number; 356 | break; 357 | case 144: 358 | entity.contextData.textColumnHeight = 359 | curr.value as number; 360 | break; 361 | case 295: 362 | entity.contextData.textUseWordBreak = 363 | curr.value as boolean; 364 | break; 365 | case 296: 366 | entity.contextData.hasBlock = curr.value as boolean; 367 | break; 368 | case 341: 369 | entity.contextData.blockContentId = 370 | curr.value as number; 371 | break; 372 | case 14: 373 | entity.contextData.blockContentNormalDirection = 374 | helpers.parsePoint(scanner); 375 | break; 376 | case 15: 377 | entity.contextData.blockContentPosition = 378 | helpers.parsePoint(scanner); 379 | break; 380 | case 16: 381 | entity.contextData.blockContentScale = 382 | curr.value as number; 383 | break; 384 | case 46: 385 | entity.contextData.blockContentRotation = 386 | curr.value as number; 387 | break; 388 | case 93: 389 | entity.contextData.blockContentColor = 390 | curr.value as number; 391 | break; 392 | case 47: 393 | entity.contextData.blockTransformationMatrix = helpers.parseMatrix(scanner, 47); 394 | break; 395 | case 110: 396 | entity.contextData.planeOriginPoint = 397 | helpers.parsePoint(scanner); 398 | break; 399 | case 111: 400 | entity.contextData.planeXAxisDirection = 401 | helpers.parsePoint(scanner); 402 | break; 403 | case 112: 404 | entity.contextData.planeYAxisDirection = 405 | helpers.parsePoint(scanner); 406 | break; 407 | case 297: 408 | entity.contextData.planeNormalReversed = 409 | curr.value as boolean; 410 | break; 411 | case 301: // END CONTEXT_DATA 412 | return; 413 | case 302: // START LEADER 414 | parseLeaderData(); 415 | break; 416 | default: 417 | break; 418 | } 419 | 420 | curr = scanner.next(); 421 | } 422 | } 423 | 424 | function parseLeaderData() { 425 | const leader = { 426 | leaderLines: [], 427 | } as any as IMLeaderLeader; 428 | 429 | entity.contextData.leaders.push(leader); 430 | 431 | while (!scanner.isEOF()) { 432 | switch (curr.code) { 433 | case 290: 434 | leader.hasSetLastLeaderLinePoint = 435 | curr.value as boolean; 436 | break; 437 | case 291: 438 | leader.hasSetDoglegVector = curr.value as boolean; 439 | break; 440 | case 10: 441 | leader.lastLeaderLinePoint = 442 | helpers.parsePoint(scanner); 443 | break; 444 | case 11: 445 | leader.doglegVector = helpers.parsePoint(scanner); 446 | break; 447 | case 90: 448 | leader.leaderBranchIndex = curr.value as number; 449 | break; 450 | case 40: 451 | leader.doglegLength = curr.value as number; 452 | break; 453 | case 303: // END LEADER 454 | return; 455 | case 304: // START LEADER_LINE 456 | parseLeaderLineData(); 457 | break; 458 | default: 459 | break; 460 | } 461 | 462 | curr = scanner.next(); 463 | } 464 | } 465 | 466 | function parseLeaderLineData() { 467 | const leader = 468 | entity.contextData.leaders[ 469 | entity.contextData.leaders.length - 1 470 | ]; 471 | const line = { 472 | vertices: [[]], 473 | } as any as IMLeaderLine; 474 | leader.leaderLines.push(line); 475 | 476 | while (!scanner.isEOF()) { 477 | switch (curr.code) { 478 | case 10: 479 | line.vertices[0].push(helpers.parsePoint(scanner)); 480 | break; 481 | case 305: // END LEADER_LINE 482 | return; 483 | default: 484 | break; 485 | } 486 | 487 | curr = scanner.next(); 488 | } 489 | } 490 | 491 | parseCommonData(); 492 | 493 | return entity; 494 | } 495 | } 496 | -------------------------------------------------------------------------------- /src/entities/mtext.ts: -------------------------------------------------------------------------------- 1 | import DxfArrayScanner, { IGroup } from '../DxfArrayScanner.js'; 2 | import * as helpers from '../ParseHelpers.js'; 3 | import IGeometry, { IEntity, IPoint } from './geomtry.js'; 4 | 5 | export interface IMtextEntity extends IEntity { 6 | text: string; 7 | position: IPoint; 8 | directionVector: IPoint; 9 | height: number; 10 | width: number; 11 | rotation: number; 12 | attachmentPoint: number; 13 | drawingDirection: number; 14 | } 15 | 16 | export default class Mtext implements IGeometry { 17 | public ForEntityName = 'MTEXT' as const; 18 | public parseEntity(scanner: DxfArrayScanner, curr: IGroup) { 19 | const entity = { type: curr.value } as IMtextEntity; 20 | curr = scanner.next(); 21 | while (!scanner.isEOF()) { 22 | if (curr.code === 0) break; 23 | 24 | switch (curr.code) { 25 | case 3: 26 | entity.text ? entity.text += curr.value : entity.text = curr.value as string; 27 | break; 28 | case 1: 29 | entity.text ? entity.text += curr.value : entity.text = curr.value as string; 30 | break; 31 | case 10: 32 | entity.position = helpers.parsePoint(scanner); 33 | break; 34 | case 11: 35 | entity.directionVector = helpers.parsePoint(scanner); 36 | break; 37 | case 40: 38 | //Note: this is the text height 39 | entity.height = curr.value as number; 40 | break; 41 | case 41: 42 | entity.width = curr.value as number; 43 | break; 44 | case 50: 45 | entity.rotation = curr.value as number; 46 | break; 47 | case 71: 48 | entity.attachmentPoint = curr.value as number; 49 | break; 50 | case 72: 51 | entity.drawingDirection = curr.value as number; 52 | break; 53 | default: 54 | helpers.checkCommonEntityProperties(entity, curr, scanner); 55 | break; 56 | } 57 | curr = scanner.next(); 58 | } 59 | return entity; 60 | } 61 | } 62 | -------------------------------------------------------------------------------- /src/entities/point.ts: -------------------------------------------------------------------------------- 1 | import DxfArrayScanner, { IGroup } from '../DxfArrayScanner.js'; 2 | import * as helpers from '../ParseHelpers.js'; 3 | import IGeometry, { IEntity, IPoint } from './geomtry.js'; 4 | 5 | export interface IPointEntity extends IEntity{ 6 | position: IPoint; 7 | thickness: number; 8 | extrusionDirection: IPoint; 9 | } 10 | 11 | export default class Point implements IGeometry{ 12 | public ForEntityName= 'POINT' as const; 13 | public parseEntity(scanner: DxfArrayScanner, curr: IGroup) { 14 | const type = curr.value as string; 15 | const entity = { type } as unknown as IPointEntity; 16 | curr = scanner.next(); 17 | while(!scanner.isEOF()) { 18 | if(curr.code === 0) break; 19 | 20 | switch(curr.code) { 21 | case 10: 22 | entity.position = helpers.parsePoint(scanner); 23 | break; 24 | case 39: 25 | entity.thickness = curr.value as number; 26 | break; 27 | case 210: 28 | entity.extrusionDirection = helpers.parsePoint(scanner); 29 | break; 30 | case 100: 31 | break; 32 | default: // check common entity attributes 33 | helpers.checkCommonEntityProperties(entity, curr, scanner); 34 | break; 35 | } 36 | curr = scanner.next(); 37 | } 38 | 39 | return entity; 40 | } 41 | } 42 | -------------------------------------------------------------------------------- /src/entities/polyline.ts: -------------------------------------------------------------------------------- 1 | import * as helpers from '../ParseHelpers.js'; 2 | import VertexParser, { IVertexEntity } from './vertex.js'; 3 | import IGeometry, { IEntity, IPoint } from './geomtry.js'; 4 | import DxfArrayScanner, { IGroup } from '../DxfArrayScanner.js'; 5 | 6 | export interface IPolylineEntity extends IEntity { 7 | vertices: IVertexEntity[]; 8 | thickness: number; 9 | shape: boolean; 10 | includesCurveFitVertices: boolean; 11 | includesSplineFitVertices: boolean; 12 | is3dPolyline: boolean; 13 | is3dPolygonMesh: boolean; 14 | is3dPolygonMeshClosed: boolean; 15 | isPolyfaceMesh: boolean; 16 | hasContinuousLinetypePattern: boolean; 17 | extrusionDirection: IPoint; 18 | } 19 | 20 | export default class Polyline implements IGeometry { 21 | public ForEntityName = 'POLYLINE' as const; 22 | public parseEntity(scanner: DxfArrayScanner, curr: IGroup) { 23 | var entity = { type: curr.value, vertices: [] as IVertexEntity[] } as IPolylineEntity; 24 | curr = scanner.next(); 25 | while (!scanner.isEOF()) { 26 | if (curr.code === 0) break; 27 | 28 | switch (curr.code) { 29 | case 10: // always 0 30 | break; 31 | case 20: // always 0 32 | break; 33 | case 30: // elevation 34 | break; 35 | case 39: // thickness 36 | entity.thickness = curr.value as number; 37 | break; 38 | case 40: // start width 39 | break; 40 | case 41: // end width 41 | break; 42 | case 70: 43 | entity.shape = ((curr.value as number) & 1) !== 0; 44 | entity.includesCurveFitVertices = ((curr.value as number) & 2) !== 0; 45 | entity.includesSplineFitVertices = ((curr.value as number) & 4) !== 0; 46 | entity.is3dPolyline = ((curr.value as number) & 8) !== 0; 47 | entity.is3dPolygonMesh = ((curr.value as number) & 16) !== 0; 48 | entity.is3dPolygonMeshClosed = ((curr.value as number) & 32) !== 0; // 32 = The polygon mesh is closed in the N direction 49 | entity.isPolyfaceMesh = ((curr.value as number) & 64) !== 0; 50 | entity.hasContinuousLinetypePattern = ((curr.value as number) & 128) !== 0; 51 | break; 52 | case 71: // Polygon mesh M vertex count 53 | break; 54 | case 72: // Polygon mesh N vertex count 55 | break; 56 | case 73: // Smooth surface M density 57 | break; 58 | case 74: // Smooth surface N density 59 | break; 60 | case 75: // Curves and smooth surface type 61 | break; 62 | case 210: 63 | entity.extrusionDirection = helpers.parsePoint(scanner); 64 | break; 65 | default: 66 | helpers.checkCommonEntityProperties(entity, curr, scanner); 67 | break; 68 | } 69 | curr = scanner.next(); 70 | } 71 | 72 | entity.vertices = parsePolylineVertices(scanner, curr); 73 | 74 | return entity; 75 | } 76 | } 77 | 78 | function parsePolylineVertices(scanner:DxfArrayScanner, curr:IGroup) { 79 | const vertexParser = new VertexParser(); 80 | 81 | const vertices = []; 82 | while (!scanner.isEOF()) { 83 | if (curr.code === 0) { 84 | if (curr.value === 'VERTEX') { 85 | vertices.push(vertexParser.parseEntity(scanner, curr)); 86 | curr = scanner.lastReadGroup; 87 | } else if (curr.value === 'SEQEND') { 88 | parseSeqEnd(scanner, curr); 89 | break; 90 | } 91 | } 92 | } 93 | return vertices; 94 | } 95 | 96 | function parseSeqEnd(scanner:DxfArrayScanner, curr: IGroup) { 97 | const entity = { type: curr.value } as IEntity; 98 | curr = scanner.next(); 99 | while (!scanner.isEOF()) { 100 | if (curr.code == 0) break; 101 | helpers.checkCommonEntityProperties(entity, curr, scanner); 102 | curr = scanner.next(); 103 | } 104 | 105 | return entity; 106 | }; 107 | -------------------------------------------------------------------------------- /src/entities/solid.ts: -------------------------------------------------------------------------------- 1 | import DxfArrayScanner, { IGroup } from '../DxfArrayScanner.js'; 2 | import * as helpers from '../ParseHelpers.js'; 3 | import IGeometry, { IEntity, IPoint } from './geomtry.js'; 4 | 5 | export interface ISolidEntity extends IEntity { 6 | points: IPoint[]; 7 | extrusionDirection: IPoint; 8 | } 9 | 10 | export default class Solid implements IGeometry { 11 | public ForEntityName = 'SOLID' as const; 12 | public parseEntity(scanner: DxfArrayScanner, curr: IGroup) { 13 | const entity = { type: curr.value, points: [] as IPoint[] } as ISolidEntity; 14 | curr = scanner.next(); 15 | while (!scanner.isEOF()) { 16 | if (curr.code === 0) break; 17 | 18 | switch (curr.code) { 19 | case 10: 20 | entity.points[0] = helpers.parsePoint(scanner); 21 | break; 22 | case 11: 23 | entity.points[1] = helpers.parsePoint(scanner); 24 | break; 25 | case 12: 26 | entity.points[2] = helpers.parsePoint(scanner); 27 | break; 28 | case 13: 29 | entity.points[3] = helpers.parsePoint(scanner); 30 | break; 31 | case 210: 32 | entity.extrusionDirection = helpers.parsePoint(scanner); 33 | break; 34 | default: // check common entity attributes 35 | helpers.checkCommonEntityProperties(entity, curr, scanner); 36 | break; 37 | } 38 | curr = scanner.next(); 39 | } 40 | 41 | return entity; 42 | } 43 | } 44 | -------------------------------------------------------------------------------- /src/entities/spline.ts: -------------------------------------------------------------------------------- 1 | import DxfArrayScanner, { IGroup } from '../DxfArrayScanner.js'; 2 | import * as helpers from '../ParseHelpers.js'; 3 | import IGeometry, { IEntity, IPoint } from './geomtry.js'; 4 | 5 | export interface ISplineEntity extends IEntity { 6 | controlPoints?: IPoint[]; 7 | fitPoints?: IPoint[]; 8 | startTangent: IPoint; 9 | endTangent: IPoint; 10 | knotValues: number[]; 11 | closed: boolean; 12 | periodic: boolean; 13 | rational: boolean; 14 | planar: boolean; 15 | linear: boolean; 16 | degreeOfSplineCurve: number; 17 | numberOfKnots: number; 18 | numberOfControlPoints: number; 19 | numberOfFitPoints: number; 20 | normalVector: IPoint; 21 | } 22 | 23 | export default class Spline implements IGeometry { 24 | public ForEntityName = 'SPLINE' as const; 25 | public parseEntity(scanner: DxfArrayScanner, curr: IGroup) { 26 | const entity = { type: curr.value } as ISplineEntity; 27 | curr = scanner.next(); 28 | while (!scanner.isEOF()) { 29 | if (curr.code === 0) break; 30 | 31 | switch (curr.code) { 32 | case 10: 33 | if (!entity.controlPoints) entity.controlPoints = []; 34 | entity.controlPoints.push(helpers.parsePoint(scanner)); 35 | break; 36 | case 11: 37 | if (!entity.fitPoints) entity.fitPoints = []; 38 | entity.fitPoints.push(helpers.parsePoint(scanner)); 39 | break; 40 | case 12: 41 | entity.startTangent = helpers.parsePoint(scanner); 42 | break; 43 | case 13: 44 | entity.endTangent = helpers.parsePoint(scanner); 45 | break; 46 | case 40: 47 | if (!entity.knotValues) entity.knotValues = []; 48 | entity.knotValues.push(curr.value as number); 49 | break; 50 | case 70: 51 | if (((curr.value as number) & 1) != 0) entity.closed = true; 52 | if (((curr.value as number) & 2) != 0) entity.periodic = true; 53 | if (((curr.value as number) & 4) != 0) entity.rational = true; 54 | if (((curr.value as number) & 8) != 0) entity.planar = true; 55 | if (((curr.value as number) & 16) != 0) { 56 | entity.planar = true; 57 | entity.linear = true; 58 | } 59 | break; 60 | 61 | case 71: 62 | entity.degreeOfSplineCurve = curr.value as number; 63 | break; 64 | case 72: 65 | entity.numberOfKnots = curr.value as number; 66 | break; 67 | case 73: 68 | entity.numberOfControlPoints = curr.value as number; 69 | break; 70 | case 74: 71 | entity.numberOfFitPoints = curr.value as number; 72 | break; 73 | case 210: 74 | entity.normalVector = helpers.parsePoint(scanner); 75 | break; 76 | default: 77 | helpers.checkCommonEntityProperties(entity, curr, scanner); 78 | break; 79 | } 80 | curr = scanner.next(); 81 | } 82 | 83 | return entity; 84 | } 85 | } 86 | -------------------------------------------------------------------------------- /src/entities/text.ts: -------------------------------------------------------------------------------- 1 | import DxfArrayScanner, { IGroup } from '../DxfArrayScanner.js'; 2 | import * as helpers from '../ParseHelpers.js'; 3 | import IGeometry, { IEntity, IPoint } from './geomtry.js'; 4 | 5 | export interface ITextEntity extends IEntity { 6 | startPoint: IPoint; 7 | endPoint: IPoint; 8 | textHeight: number; 9 | xScale: number; 10 | rotation: number; 11 | text: string; 12 | halign: number; 13 | valign: number; 14 | } 15 | 16 | export default class Text implements IGeometry { 17 | public ForEntityName = 'TEXT' as const; 18 | public parseEntity(scanner: DxfArrayScanner, curr: IGroup) { 19 | const entity = { type: curr.value } as ITextEntity; 20 | curr = scanner.next(); 21 | while (!scanner.isEOF()) { 22 | if (curr.code === 0) break; 23 | switch (curr.code) { 24 | case 10: // X coordinate of 'first alignment point' 25 | entity.startPoint = helpers.parsePoint(scanner); 26 | break; 27 | case 11: // X coordinate of 'second alignment point' 28 | entity.endPoint = helpers.parsePoint(scanner); 29 | break; 30 | case 40: // Text height 31 | entity.textHeight = curr.value as number; 32 | break; 33 | case 41: 34 | entity.xScale = curr.value as number; 35 | break; 36 | case 50: // Rotation in degrees 37 | entity.rotation = curr.value as number; 38 | break; 39 | case 1: // Text 40 | entity.text = curr.value as string; 41 | break; 42 | // NOTE: 72 and 73 are meaningless without 11 (second alignment point) 43 | case 72: // Horizontal alignment 44 | entity.halign = curr.value as number; 45 | break; 46 | case 73: // Vertical alignment 47 | entity.valign = curr.value as number; 48 | break; 49 | default: // check common entity attributes 50 | helpers.checkCommonEntityProperties(entity, curr, scanner); 51 | break; 52 | } 53 | curr = scanner.next(); 54 | } 55 | return entity; 56 | } 57 | } 58 | -------------------------------------------------------------------------------- /src/entities/vertex.ts: -------------------------------------------------------------------------------- 1 | import DxfArrayScanner, { IGroup } from '../DxfArrayScanner.js'; 2 | import * as helpers from '../ParseHelpers.js'; 3 | import IGeometry, { IEntity, IPoint } from './geomtry.js'; 4 | 5 | export interface IVertexEntity extends IEntity, IPoint{ 6 | bulge: number; 7 | curveFittingVertex: boolean; 8 | curveFitTangent: boolean; 9 | splineVertex: boolean; 10 | splineControlPoint: boolean; 11 | threeDPolylineVertex: boolean; 12 | threeDPolylineMesh: boolean; 13 | polyfaceMeshVertex: boolean; 14 | faceA: number; 15 | faceB: number; 16 | faceC: number; 17 | faceD: number; 18 | } 19 | 20 | export default class Vertex implements IGeometry { 21 | public ForEntityName= 'VERTEX' as const; 22 | public parseEntity(scanner: DxfArrayScanner, curr: IGroup) { 23 | var entity = { type: curr.value } as IVertexEntity; 24 | curr = scanner.next(); 25 | while(!scanner.isEOF()) { 26 | if(curr.code === 0) break; 27 | 28 | switch(curr.code) { 29 | case 10: // X 30 | entity.x = curr.value as number; 31 | break; 32 | case 20: // Y 33 | entity.y = curr.value as number; 34 | break; 35 | case 30: // Z 36 | entity.z = curr.value as number; 37 | break; 38 | case 40: // start width 39 | break; 40 | case 41: // end width 41 | break; 42 | case 42: // bulge 43 | if(curr.value != 0) entity.bulge = curr.value as number; 44 | break; 45 | case 70: // flags 46 | entity.curveFittingVertex = ((curr.value as number) & 1) !== 0; 47 | entity.curveFitTangent = ((curr.value as number) & 2) !== 0; 48 | entity.splineVertex = ((curr.value as number) & 8) !== 0; 49 | entity.splineControlPoint = ((curr.value as number) & 16) !== 0; 50 | entity.threeDPolylineVertex = ((curr.value as number) & 32) !== 0; 51 | entity.threeDPolylineMesh = ((curr.value as number) & 64) !== 0; 52 | entity.polyfaceMeshVertex = ((curr.value as number) & 128) !== 0; 53 | break; 54 | case 50: // curve fit tangent direction 55 | break; 56 | case 71: // polyface mesh vertex index 57 | entity.faceA = curr.value as number; 58 | break; 59 | case 72: // polyface mesh vertex index 60 | entity.faceB = curr.value as number; 61 | break; 62 | case 73: // polyface mesh vertex index 63 | entity.faceC = curr.value as number; 64 | break; 65 | case 74: // polyface mesh vertex index 66 | entity.faceD = curr.value as number; 67 | break; 68 | default: 69 | helpers.checkCommonEntityProperties(entity, curr, scanner); 70 | break; 71 | } 72 | 73 | curr = scanner.next(); 74 | } 75 | return entity; 76 | } 77 | } 78 | -------------------------------------------------------------------------------- /src/index.ts: -------------------------------------------------------------------------------- 1 | export { default, default as DxfParser } from './DxfParser.js'; 2 | export { IDxf, IBlock, ILayerTypesTable, ILayersTable, ITables, IViewPortTable, IBaseTable, ILayer, ILayerTableDefinition, ILineType, ILineTypeTableDefinition, ITable, ITableDefinitions, IViewPort, IViewPortTableDefinition } from './DxfParser.js'; 3 | export { IEntity, IPoint } from './entities/geomtry.js'; 4 | export { I3DfaceEntity } from './entities/3dface.js'; 5 | export { IArcEntity } from './entities/arc.js'; 6 | export { IAttdefEntity } from './entities/attdef.js'; 7 | export { ICircleEntity } from './entities/circle.js'; 8 | export { IDimensionEntity } from './entities/dimension.js'; 9 | export { ILeaderEntity } from './entities/mleader.js'; 10 | export { IEllipseEntity } from './entities/ellipse.js'; 11 | export { IInsertEntity } from './entities/insert.js'; 12 | export { ILineEntity } from './entities/line.js'; 13 | export { ILwpolylineEntity } from './entities/lwpolyline.js'; 14 | export { IMtextEntity } from './entities/mtext.js'; 15 | export { IPointEntity } from './entities/point.js'; 16 | export { IPolylineEntity } from './entities/polyline.js'; 17 | export { ISolidEntity } from './entities/solid.js'; 18 | export { ISplineEntity } from './entities/spline.js'; 19 | export { ITextEntity } from './entities/text.js'; 20 | export { IVertexEntity } from './entities/vertex.js'; 21 | -------------------------------------------------------------------------------- /test/DxfArrayScanner.test.js: -------------------------------------------------------------------------------- 1 | import Scanner from '../esm/DxfArrayScanner.js'; 2 | import 'should'; 3 | 4 | describe('Scanner', function() { 5 | describe('.hasNext()', function() { 6 | it('should return false when the array is empty', function() { 7 | var scanner = new Scanner([]); 8 | scanner.hasNext().should.be.false; 9 | }); 10 | 11 | it('should return false when the array has length 1', function() { 12 | var scanner = new Scanner(['1']); 13 | scanner.hasNext().should.be.false; 14 | }); 15 | 16 | it('should return true when the array has length 2', function() { 17 | var scanner = new Scanner(['1','2']); 18 | scanner.hasNext().should.be.true; 19 | }); 20 | 21 | it('should return false when the array has length 4 and pointer is on the last element', function() { 22 | var scanner = new Scanner(['1','2','3','4']); 23 | scanner._pointer = scanner._data.length - 1; 24 | scanner.hasNext().should.be.false; 25 | }); 26 | 27 | it('should return true when the array has length 4 and pointer is on the second-to-last element', function() { 28 | var scanner = new Scanner(['1','2','3','4']); 29 | scanner._pointer = scanner._data.length - 2; 30 | scanner.hasNext().should.be.true; 31 | }); 32 | }); 33 | 34 | describe('.next()', function() { 35 | it('should throw an error when the array is empty', function() { 36 | var scanner = new Scanner([]); 37 | scanner.next.bind(scanner).should.throw(/Unexpected end of input/); 38 | }); 39 | it('should throw an error when the array has only 1 element', function() { 40 | var scanner = new Scanner(['1']); 41 | scanner.next.bind(scanner).should.throw(/Unexpected end of input/); 42 | }); 43 | it('should throw an error when next is called and eof has already been read', function(){ 44 | var scanner = new Scanner(['1','2']); 45 | scanner._eof = true; 46 | scanner.next.bind(scanner).should.throw(/Cannot call \'next\' after EOF/); 47 | }); 48 | it('should return the 1st and 2nd index as the code and value respectively', function() { 49 | var scanner = new Scanner(['1','2']); 50 | var result = scanner.next(); 51 | result.should.eql({ code: 1, value: '2'}); 52 | }); 53 | it('should set _eof to true when EOF code-value pair is read', function() { 54 | var scanner = new Scanner(['0','EOF']); 55 | scanner.next(); 56 | scanner._eof.should.be.true; 57 | }); 58 | it('should increment the pointer by 2', function() { 59 | var scanner = new Scanner(['1','2']); 60 | scanner.next(); 61 | scanner._pointer.should.eql(2); 62 | }); 63 | }); 64 | describe('.isEOF()', function() { 65 | it('should be true when _eof is true', function() { 66 | var scanner = new Scanner(['0','EOF']); 67 | scanner._eof = true; 68 | scanner.isEOF().should.be.true; 69 | }); 70 | }); 71 | }); -------------------------------------------------------------------------------- /test/DxfParser.test.js: -------------------------------------------------------------------------------- 1 | import * as fs from 'fs'; 2 | import * as path from 'path'; 3 | import DxfParser from '../esm/index.js'; 4 | import should from 'should'; 5 | import approvals from 'approvals'; 6 | 7 | // Note: fialOnLineEndingDifferences doesn't appear to work right now. Filed an issue with approvals. 8 | approvals.configure({ 9 | reporters: [ 10 | 'vscode', 11 | 'opendiff', 12 | 'p4merge', 13 | 'tortoisemerge', 14 | 'nodediff', 15 | 'gitdiff' 16 | ], 17 | normalizeLineEndingsTo: '\n', 18 | EOL: '\n', 19 | maxLaunches: 5, 20 | failOnLineEndingDifferences: false, 21 | stripBOM: true, 22 | }); 23 | 24 | const __dirname = path.dirname(new URL(import.meta.url).pathname) 25 | 26 | describe('Parser', function() { 27 | 28 | it('should parse the dxf header variables into an object', function(done) { 29 | var file = fs.createReadStream(__dirname + '/data/header.dxf', { encoding: 'utf8' }); 30 | var parser = new DxfParser(); 31 | 32 | parser.parseStream(file).then((result) => { 33 | var expected = fs.readFileSync(__dirname + '/data/header.parser.out', {encoding: 'utf8'}); 34 | result.should.eql(JSON.parse(expected)); 35 | done(); 36 | }, (err) => { 37 | should.not.exist(err); 38 | }); 39 | }); 40 | 41 | var tables; 42 | 43 | it('should parse the tables section without error', function(done) { 44 | var file = fs.createReadStream(__dirname + '/data/tables.dxf', { encoding: 'utf8' }); 45 | var parser = new DxfParser(); 46 | 47 | parser.parseStream(file).then((result) => { 48 | tables = result.tables; 49 | fs.writeFileSync(path.join(__dirname, 'data', 'layer-table.actual.json'), JSON.stringify(tables.layer, null, 2)); 50 | fs.writeFileSync(path.join(__dirname, 'data', 'ltype-table.actual.json'), JSON.stringify(tables.lineType, null, 2)); 51 | fs.writeFileSync(path.join(__dirname, 'data', 'viewport-table.actual.json'), JSON.stringify(tables.viewPort, null, 2)); 52 | done(); 53 | }, (err) => { 54 | var errMsg = err ? err.stack : undefined; 55 | should.not.exist(err, errMsg); 56 | }) 57 | }); 58 | 59 | it('should parse the dxf layers', function() { 60 | should.exist(tables); 61 | tables.should.have.property('layer'); 62 | 63 | var expectedOutputFilePath = path.join(__dirname,'data','layer-table.expected.json'); 64 | 65 | var expected = fs.readFileSync(expectedOutputFilePath, {encoding: 'utf8'}); 66 | tables.layer.should.eql(JSON.parse(expected)); 67 | }); 68 | 69 | it('should parse the dxf ltype table', function() { 70 | should.exist(tables); 71 | tables.should.have.property('lineType'); 72 | 73 | var expectedOutputFilePath = path.join(__dirname,'data','ltype-table.expected.json'); 74 | 75 | var expected = fs.readFileSync(expectedOutputFilePath, {encoding: 'utf8'}); 76 | tables.lineType.should.eql(JSON.parse(expected)); 77 | }); 78 | 79 | it('should parse the dxf viewPort table', function() { 80 | should.exist(tables); 81 | tables.should.have.property('viewPort'); 82 | 83 | var expectedOutputFilePath = path.join(__dirname,'data','viewport-table.expected.json'); 84 | 85 | var expected = fs.readFileSync(expectedOutputFilePath, {encoding: 'utf8'}); 86 | tables.viewPort.should.eql(JSON.parse(expected)); 87 | }); 88 | 89 | it('should parse a complex BLOCKS section', function() { 90 | verifyDxf(path.join(__dirname, 'data', 'blocks.dxf')) 91 | }); 92 | 93 | it('should parse a simple BLOCKS section', function() { 94 | var file = fs.readFileSync(path.join(__dirname, 'data', 'blocks2.dxf'), 'utf8'); 95 | 96 | var parser = new DxfParser(); 97 | var dxf; 98 | try { 99 | dxf = parser.parseSync(file); 100 | fs.writeFileSync(path.join(__dirname, 'data', 'blocks2.actual.json'), JSON.stringify(dxf, null, 2)); 101 | }catch(err) { 102 | should.not.exist(err); 103 | } 104 | should.exist(dxf); 105 | 106 | 107 | var expected = fs.readFileSync(path.join(__dirname, 'data', 'blocks2.expected.json'), {encoding: 'utf8'}); 108 | dxf.should.eql(JSON.parse(expected)); 109 | }); 110 | 111 | it('should parse POLYLINES', function() { 112 | verifyDxf(path.join(__dirname, 'data', 'polylines.dxf')); 113 | }); 114 | 115 | it('should parse ELLIPSE entities', function() { 116 | var file = fs.readFileSync(path.join(__dirname, 'data', 'ellipse.dxf'), 'utf8'); 117 | 118 | var parser = new DxfParser(); 119 | var dxf; 120 | try { 121 | dxf = parser.parseSync(file); 122 | fs.writeFileSync(path.join(__dirname, 'data', 'ellipse.actual.json'), JSON.stringify(dxf, null, 2)); 123 | }catch(err) { 124 | should.not.exist(err); 125 | } 126 | should.exist(dxf); 127 | 128 | 129 | var expected = fs.readFileSync(path.join(__dirname, 'data', 'ellipse.expected.json'), {encoding: 'utf8'}); 130 | dxf.should.eql(JSON.parse(expected)); 131 | }); 132 | 133 | it('should parse SPLINE entities', function() { 134 | var file = fs.readFileSync(path.join(__dirname, 'data', 'splines.dxf'), 'utf8'); 135 | 136 | var parser = new DxfParser(); 137 | var dxf; 138 | try { 139 | dxf = parser.parseSync(file); 140 | fs.writeFileSync(path.join(__dirname, 'data', 'splines.actual.json'), JSON.stringify(dxf, null, 2)); 141 | }catch(err) { 142 | should.not.exist(err); 143 | } 144 | should.exist(dxf); 145 | 146 | var expected = fs.readFileSync(path.join(__dirname, 'data', 'splines.expected.json'), {encoding: 'utf8'}); 147 | dxf.should.eql(JSON.parse(expected)); 148 | }); 149 | 150 | it('should parse EXTENDED DATA', function() { 151 | var file = fs.readFileSync(path.join(__dirname, 'data', 'extendeddata.dxf'), 'utf8'); 152 | 153 | var parser = new DxfParser(); 154 | var dxf; 155 | try { 156 | dxf = parser.parseSync(file); 157 | fs.writeFileSync(path.join(__dirname, 'data', 'extendeddata.actual.json'), JSON.stringify(dxf, null, 2)); 158 | }catch(err) { 159 | should.not.exist(err); 160 | } 161 | should.exist(dxf); 162 | 163 | var expected = fs.readFileSync(path.join(__dirname, 'data', 'extendeddata.expected.json'), {encoding: 'utf8'}); 164 | dxf.should.eql(JSON.parse(expected)); 165 | }); 166 | 167 | it('should parse SPLINE entities that are like arcs and circles', function() { 168 | verifyDxf(path.join(__dirname, 'data', 'arcs-as-splines.dxf')); 169 | }); 170 | 171 | it('should parse ARC entities (1)', function() { 172 | verifyDxf(path.join(__dirname, 'data', 'arc1.dxf')); 173 | }); 174 | 175 | it('should parse MTEXT entities', function() { 176 | verifyDxf(path.join(__dirname, 'data', 'mtext-test.dxf')); 177 | }); 178 | 179 | it('should parse MULTILEADER entities', function() { 180 | verifyDxf(path.join(__dirname, 'data', 'leaders.dxf')); 181 | }); 182 | }); 183 | 184 | function verifyDxf(sourceFilePath) { 185 | var baseName = path.basename(sourceFilePath, '.dxf'); 186 | var sourceDirectory = path.dirname(sourceFilePath); 187 | 188 | var file = fs.readFileSync(sourceFilePath, 'utf8'); 189 | 190 | var parser = new DxfParser(); 191 | var dxf = parser.parse(file); 192 | 193 | approvals.verifyAsJSON(sourceDirectory, baseName, dxf); 194 | } -------------------------------------------------------------------------------- /test/data/arc1.approved.txt: -------------------------------------------------------------------------------- 1 | { 2 | "entities": [ 3 | { 4 | "angleLength": 0.28231298336862665, 5 | "center": { 6 | "x": 650.0541823996996, 7 | "y": 347.5909732684974, 8 | "z": 0 9 | }, 10 | "color": 0, 11 | "colorIndex": 0, 12 | "endAngle": 6.197231758053196, 13 | "extrusionDirectionX": 0, 14 | "extrusionDirectionY": 0, 15 | "extrusionDirectionZ": -1, 16 | "handle": "B484", 17 | "layer": "FG-Dtl-Dim", 18 | "lineType": "ByBlock", 19 | "lineweight": -2, 20 | "ownerHandle": "3706", 21 | "radius": 0.7604262403327394, 22 | "startAngle": 5.914918774684569, 23 | "type": "ARC" 24 | } 25 | ] 26 | } 27 | -------------------------------------------------------------------------------- /test/data/arc1.dxf: -------------------------------------------------------------------------------- 1 | 0 2 | SECTION 3 | 2 4 | ENTITIES 5 | 0 6 | ARC 7 | 5 8 | B484 9 | 330 10 | 3706 11 | 100 12 | AcDbEntity 13 | 8 14 | FG-Dtl-Dim 15 | 6 16 | ByBlock 17 | 62 18 | 0 19 | 370 20 | -2 21 | 100 22 | AcDbCircle 23 | 10 24 | 650.0541823996996 25 | 20 26 | 347.5909732684974 27 | 30 28 | 0.0 29 | 40 30 | 0.7604262403327394 31 | 210 32 | 0.0 33 | 220 34 | 0.0 35 | 230 36 | -1.0 37 | 100 38 | AcDbArc 39 | 50 40 | 338.8998819521181 41 | 51 42 | 355.0752244008874 43 | 0 44 | ENDSEC 45 | 0 46 | EOF -------------------------------------------------------------------------------- /test/data/arcs-as-splines.approved.txt: -------------------------------------------------------------------------------- 1 | { 2 | "entities": [ 3 | { 4 | "closed": true, 5 | "controlPoints": [ 6 | { 7 | "x": 233.6663114494559, 8 | "y": 180.0700474977344, 9 | "z": 0 10 | }, 11 | { 12 | "x": 233.6663114494559, 13 | "y": 212.3902435891571, 14 | "z": 0 15 | }, 16 | { 17 | "x": 201.3461153580332, 18 | "y": 212.390243589157, 19 | "z": 0 20 | }, 21 | { 22 | "x": 169.0259192666106, 23 | "y": 212.3902435891571, 24 | "z": 0 25 | }, 26 | { 27 | "x": 169.0259192666106, 28 | "y": 180.0700474977344, 29 | "z": 0 30 | }, 31 | { 32 | "x": 169.0259192666106, 33 | "y": 147.7498514063117, 34 | "z": 0 35 | }, 36 | { 37 | "x": 201.3461153580332, 38 | "y": 147.7498514063117, 39 | "z": 0 40 | }, 41 | { 42 | "x": 233.6663114494559, 43 | "y": 147.7498514063117, 44 | "z": 0 45 | }, 46 | { 47 | "x": 233.6663114494559, 48 | "y": 180.0700474977344, 49 | "z": 0 50 | } 51 | ], 52 | "degreeOfSplineCurve": 2, 53 | "handle": "6E", 54 | "knotValues": [ 55 | 0, 56 | 0, 57 | 0, 58 | 17.27875959474386, 59 | 17.27875959474386, 60 | 34.55751918948772, 61 | 34.55751918948772, 62 | 51.83627878423158, 63 | 51.83627878423158, 64 | 69.11503837897544, 65 | 69.11503837897544, 66 | 69.11503837897544 67 | ], 68 | "normalVector": { 69 | "x": 0, 70 | "y": 0, 71 | "z": 1 72 | }, 73 | "numberOfControlPoints": 9, 74 | "numberOfFitPoints": 0, 75 | "numberOfKnots": 12, 76 | "ownerHandle": "1F", 77 | "periodic": true, 78 | "planar": true, 79 | "rational": true, 80 | "type": "SPLINE" 81 | }, 82 | { 83 | "closed": true, 84 | "controlPoints": [ 85 | { 86 | "x": 208.6916144697202, 87 | "y": 243.2413398582423, 88 | "z": 0 89 | }, 90 | { 91 | "x": 208.6916144697202, 92 | "y": 250.5868389699293, 93 | "z": 0 94 | }, 95 | { 96 | "x": 201.3461153580332, 97 | "y": 250.5868389699293, 98 | "z": 0 99 | }, 100 | { 101 | "x": 194.0006162463463, 102 | "y": 250.5868389699293, 103 | "z": 0 104 | }, 105 | { 106 | "x": 194.0006162463463, 107 | "y": 243.2413398582423, 108 | "z": 0 109 | }, 110 | { 111 | "x": 194.0006162463463, 112 | "y": 235.8958407465554, 113 | "z": 0 114 | }, 115 | { 116 | "x": 201.3461153580332, 117 | "y": 235.8958407465553, 118 | "z": 0 119 | }, 120 | { 121 | "x": 208.6916144697202, 122 | "y": 235.8958407465554, 123 | "z": 0 124 | }, 125 | { 126 | "x": 208.6916144697202, 127 | "y": 243.2413398582423, 128 | "z": 0 129 | } 130 | ], 131 | "degreeOfSplineCurve": 2, 132 | "handle": "6F", 133 | "knotValues": [ 134 | 0, 135 | 0, 136 | 0, 137 | 3.926990816987241, 138 | 3.926990816987241, 139 | 7.853981633974483, 140 | 7.853981633974483, 141 | 11.78097245096172, 142 | 11.78097245096172, 143 | 15.70796326794897, 144 | 15.70796326794897, 145 | 15.70796326794897 146 | ], 147 | "normalVector": { 148 | "x": 0, 149 | "y": 0, 150 | "z": 1 151 | }, 152 | "numberOfControlPoints": 9, 153 | "numberOfFitPoints": 0, 154 | "numberOfKnots": 12, 155 | "ownerHandle": "1F", 156 | "periodic": true, 157 | "planar": true, 158 | "rational": true, 159 | "type": "SPLINE" 160 | }, 161 | { 162 | "controlPoints": [ 163 | { 164 | "x": 280.7529837541637, 165 | "y": 303.6705820088653, 166 | "z": 0 167 | }, 168 | { 169 | "x": 258.47226626445, 170 | "y": 317.9847757821756, 171 | "z": 0 172 | }, 173 | { 174 | "x": 232.5957563534457, 175 | "y": 323.6179587245282, 176 | "z": 0 177 | } 178 | ], 179 | "degreeOfSplineCurve": 2, 180 | "handle": "73", 181 | "knotValues": [ 182 | 0, 183 | 0, 184 | 0, 185 | 17.83485687076171, 186 | 17.83485687076171, 187 | 17.83485687076171 188 | ], 189 | "normalVector": { 190 | "x": 0, 191 | "y": 0, 192 | "z": 1 193 | }, 194 | "numberOfControlPoints": 3, 195 | "numberOfFitPoints": 0, 196 | "numberOfKnots": 6, 197 | "ownerHandle": "1F", 198 | "planar": true, 199 | "rational": true, 200 | "type": "SPLINE" 201 | } 202 | ] 203 | } 204 | -------------------------------------------------------------------------------- /test/data/arcs-as-splines.dxf: -------------------------------------------------------------------------------- 1 | 0 2 | SECTION 3 | 2 4 | ENTITIES 5 | 0 6 | SPLINE 7 | 5 8 | 6E 9 | 330 10 | 1F 11 | 100 12 | AcDbEntity 13 | 100 14 | AcDbSpline 15 | 210 16 | 0.0 17 | 220 18 | 0.0 19 | 230 20 | 1.0 21 | 70 22 | 15 23 | 71 24 | 2 25 | 72 26 | 12 27 | 73 28 | 9 29 | 74 30 | 0 31 | 42 32 | 0.000000001 33 | 43 34 | 0.0000000001 35 | 40 36 | 0.0 37 | 40 38 | 0.0 39 | 40 40 | 0.0 41 | 40 42 | 17.27875959474386 43 | 40 44 | 17.27875959474386 45 | 40 46 | 34.55751918948772 47 | 40 48 | 34.55751918948772 49 | 40 50 | 51.83627878423158 51 | 40 52 | 51.83627878423158 53 | 40 54 | 69.11503837897544 55 | 40 56 | 69.11503837897544 57 | 40 58 | 69.11503837897544 59 | 10 60 | 233.6663114494559 61 | 20 62 | 180.0700474977344 63 | 30 64 | 0.0 65 | 41 66 | 1.0 67 | 10 68 | 233.6663114494559 69 | 20 70 | 212.3902435891571 71 | 30 72 | 0.0 73 | 41 74 | 0.7071067811865476 75 | 10 76 | 201.3461153580332 77 | 20 78 | 212.390243589157 79 | 30 80 | 0.0 81 | 41 82 | 1.0 83 | 10 84 | 169.0259192666106 85 | 20 86 | 212.3902435891571 87 | 30 88 | 0.0 89 | 41 90 | 0.7071067811865476 91 | 10 92 | 169.0259192666106 93 | 20 94 | 180.0700474977344 95 | 30 96 | 0.0 97 | 41 98 | 1.0 99 | 10 100 | 169.0259192666106 101 | 20 102 | 147.7498514063117 103 | 30 104 | 0.0 105 | 41 106 | 0.7071067811865476 107 | 10 108 | 201.3461153580332 109 | 20 110 | 147.7498514063117 111 | 30 112 | 0.0 113 | 41 114 | 1.0 115 | 10 116 | 233.6663114494559 117 | 20 118 | 147.7498514063117 119 | 30 120 | 0.0 121 | 41 122 | 0.7071067811865476 123 | 10 124 | 233.6663114494559 125 | 20 126 | 180.0700474977344 127 | 30 128 | 0.0 129 | 41 130 | 1.0 131 | 0 132 | SPLINE 133 | 5 134 | 6F 135 | 330 136 | 1F 137 | 100 138 | AcDbEntity 139 | 100 140 | AcDbSpline 141 | 210 142 | 0.0 143 | 220 144 | 0.0 145 | 230 146 | 1.0 147 | 70 148 | 15 149 | 71 150 | 2 151 | 72 152 | 12 153 | 73 154 | 9 155 | 74 156 | 0 157 | 42 158 | 0.000000001 159 | 43 160 | 0.0000000001 161 | 40 162 | 0.0 163 | 40 164 | 0.0 165 | 40 166 | 0.0 167 | 40 168 | 3.926990816987241 169 | 40 170 | 3.926990816987241 171 | 40 172 | 7.853981633974483 173 | 40 174 | 7.853981633974483 175 | 40 176 | 11.78097245096172 177 | 40 178 | 11.78097245096172 179 | 40 180 | 15.70796326794897 181 | 40 182 | 15.70796326794897 183 | 40 184 | 15.70796326794897 185 | 10 186 | 208.6916144697202 187 | 20 188 | 243.2413398582423 189 | 30 190 | 0.0 191 | 41 192 | 1.0 193 | 10 194 | 208.6916144697202 195 | 20 196 | 250.5868389699293 197 | 30 198 | 0.0 199 | 41 200 | 0.7071067811865476 201 | 10 202 | 201.3461153580332 203 | 20 204 | 250.5868389699293 205 | 30 206 | 0.0 207 | 41 208 | 1.0 209 | 10 210 | 194.0006162463463 211 | 20 212 | 250.5868389699293 213 | 30 214 | 0.0 215 | 41 216 | 0.7071067811865476 217 | 10 218 | 194.0006162463463 219 | 20 220 | 243.2413398582423 221 | 30 222 | 0.0 223 | 41 224 | 1.0 225 | 10 226 | 194.0006162463463 227 | 20 228 | 235.8958407465554 229 | 30 230 | 0.0 231 | 41 232 | 0.7071067811865476 233 | 10 234 | 201.3461153580332 235 | 20 236 | 235.8958407465553 237 | 30 238 | 0.0 239 | 41 240 | 1.0 241 | 10 242 | 208.6916144697202 243 | 20 244 | 235.8958407465554 245 | 30 246 | 0.0 247 | 41 248 | 0.7071067811865476 249 | 10 250 | 208.6916144697202 251 | 20 252 | 243.2413398582423 253 | 30 254 | 0.0 255 | 41 256 | 1.0 257 | 0 258 | SPLINE 259 | 5 260 | 73 261 | 330 262 | 1F 263 | 100 264 | AcDbEntity 265 | 100 266 | AcDbSpline 267 | 210 268 | 0.0 269 | 220 270 | 0.0 271 | 230 272 | 1.0 273 | 70 274 | 12 275 | 71 276 | 2 277 | 72 278 | 6 279 | 73 280 | 3 281 | 74 282 | 0 283 | 42 284 | 0.000000001 285 | 43 286 | 0.0000000001 287 | 40 288 | 0.0 289 | 40 290 | 0.0 291 | 40 292 | 0.0 293 | 40 294 | 17.83485687076171 295 | 40 296 | 17.83485687076171 297 | 40 298 | 17.83485687076171 299 | 10 300 | 280.7529837541637 301 | 20 302 | 303.6705820088653 303 | 30 304 | 0.0 305 | 41 306 | 1.0 307 | 10 308 | 258.47226626445 309 | 20 310 | 317.9847757821756 311 | 30 312 | 0.0 313 | 41 314 | 0.9841380061121457 315 | 10 316 | 232.5957563534457 317 | 20 318 | 323.6179587245282 319 | 30 320 | 0.0 321 | 41 322 | 1.0 323 | 0 324 | ENDSEC 325 | 0 326 | EOF 327 | -------------------------------------------------------------------------------- /test/data/blocks.dxf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gdsestimating/dxf-parser/0df7a37a4207a1f925b8d0bfffc270ff121446b4/test/data/blocks.dxf -------------------------------------------------------------------------------- /test/data/blocks2.dxf: -------------------------------------------------------------------------------- 1 | 0 2 | SECTION 3 | 2 4 | BLOCKS 5 | 0 6 | BLOCK 7 | 5 8 | 1 9 | 8 10 | 0 11 | 2 12 | $MODEL_SPACE 13 | 70 14 | 0 15 | 10 16 | 0.0 17 | 20 18 | 0.0 19 | 30 20 | 0.0 21 | 3 22 | $MODEL_SPACE 23 | 1 24 | 25 | 0 26 | ENDBLK 27 | 5 28 | 21 29 | 8 30 | 0 31 | 0 32 | BLOCK 33 | 5 34 | 2 35 | 67 36 | 1 37 | 8 38 | 0 39 | 2 40 | $PAPER_SPACE 41 | 70 42 | 0 43 | 10 44 | 0.0 45 | 20 46 | 0.0 47 | 30 48 | 0.0 49 | 3 50 | $PAPER_SPACE 51 | 1 52 | 53 | 0 54 | ENDBLK 55 | 5 56 | 1D 57 | 67 58 | 1 59 | 8 60 | 0 61 | 0 62 | ENDSEC 63 | 0 64 | EOF -------------------------------------------------------------------------------- /test/data/blocks2.expected.json: -------------------------------------------------------------------------------- 1 | { 2 | "blocks": { 3 | "$MODEL_SPACE": { 4 | "handle": "1", 5 | "layer": "0", 6 | "name": "$MODEL_SPACE", 7 | "position": { 8 | "x": 0, 9 | "y": 0, 10 | "z": 0 11 | }, 12 | "name2": "$MODEL_SPACE", 13 | "xrefPath": "" 14 | }, 15 | "$PAPER_SPACE": { 16 | "handle": "2", 17 | "paperSpace": true, 18 | "layer": "0", 19 | "name": "$PAPER_SPACE", 20 | "position": { 21 | "x": 0, 22 | "y": 0, 23 | "z": 0 24 | }, 25 | "name2": "$PAPER_SPACE", 26 | "xrefPath": "" 27 | } 28 | } 29 | } -------------------------------------------------------------------------------- /test/data/ellipse.dxf: -------------------------------------------------------------------------------- 1 | 0 2 | SECTION 3 | 2 4 | ENTITIES 5 | 0 6 | ELLIPSE 7 | 5 8 | 37c 9 | 330 10 | 1F 11 | 100 12 | AcDbEntity 13 | 8 14 | 0 15 | 6 16 | ByLayer 17 | 100 18 | AcDbEllipse 19 | 10 20 | 10.000000 21 | 20 22 | 10.000000 23 | 30 24 | 0.000000 25 | 11 26 | 10.000000 27 | 21 28 | 10.000000 29 | 31 30 | 0.000000 31 | 40 32 | 1.986299 33 | 41 34 | 0.000000 35 | 42 36 | 6.283185 37 | 0 38 | ELLIPSE 39 | 5 40 | 37d 41 | 330 42 | 1F 43 | 100 44 | AcDbEntity 45 | 8 46 | 0 47 | 6 48 | ByLayer 49 | 100 50 | AcDbEllipse 51 | 10 52 | 0.000000 53 | 20 54 | -5.000000 55 | 30 56 | 0.000000 57 | 11 58 | 0.000000 59 | 21 60 | 5.000000 61 | 31 62 | 0.000000 63 | 40 64 | 4.000000 65 | 41 66 | 0.000000 67 | 42 68 | 6.283185 69 | 0 70 | ENDSEC 71 | 0 72 | EOF -------------------------------------------------------------------------------- /test/data/ellipse.expected.json: -------------------------------------------------------------------------------- 1 | { 2 | "entities": [ 3 | { 4 | "type": "ELLIPSE", 5 | "handle": "37c", 6 | "ownerHandle": "1F", 7 | "layer": "0", 8 | "lineType": "ByLayer", 9 | "center": { 10 | "x": 10, 11 | "y": 10, 12 | "z": 0 13 | }, 14 | "majorAxisEndPoint": { 15 | "x": 10, 16 | "y": 10, 17 | "z": 0 18 | }, 19 | "axisRatio": 1.986299, 20 | "startAngle": 0, 21 | "endAngle": 6.283185 22 | }, 23 | { 24 | "type": "ELLIPSE", 25 | "handle": "37d", 26 | "ownerHandle": "1F", 27 | "layer": "0", 28 | "lineType": "ByLayer", 29 | "center": { 30 | "x": 0, 31 | "y": -5, 32 | "z": 0 33 | }, 34 | "majorAxisEndPoint": { 35 | "x": 0, 36 | "y": 5, 37 | "z": 0 38 | }, 39 | "axisRatio": 4, 40 | "startAngle": 0, 41 | "endAngle": 6.283185 42 | } 43 | ] 44 | } -------------------------------------------------------------------------------- /test/data/header.dxf: -------------------------------------------------------------------------------- 1 | 0 2 | SECTION 3 | 2 4 | HEADER 5 | 9 6 | $ACADVER 7 | 1 8 | AC1027 9 | 9 10 | $ACADMAINTVER 11 | 70 12 | 55 13 | 9 14 | $DWGCODEPAGE 15 | 3 16 | ANSI_1252 17 | 9 18 | $LASTSAVEDBY 19 | 1 20 | Shane 21 | 9 22 | $REQUIREDVERSIONS 23 | 160 24 | 0 25 | 9 26 | $INSBASE 27 | 10 28 | 0.0 29 | 20 30 | 0.0 31 | 30 32 | 0.0 33 | 9 34 | $EXTMIN 35 | 10 36 | 146.8403717847312 37 | 20 38 | 141.8294137695975 39 | 30 40 | -5.934454319554902 41 | 9 42 | $EXTMAX 43 | 10 44 | 762.6679804989191 45 | 20 46 | 545.821967323924 47 | 30 48 | 6.065545680445099 49 | 9 50 | $LIMMIN 51 | 10 52 | 0.0 53 | 20 54 | 0.0 55 | 9 56 | $LIMMAX 57 | 10 58 | 1000.0 59 | 20 60 | 800.0 61 | 9 62 | $ORTHOMODE 63 | 70 64 | 1 65 | 9 66 | $REGENMODE 67 | 70 68 | 1 69 | 9 70 | $FILLMODE 71 | 70 72 | 1 73 | 9 74 | $QTEXTMODE 75 | 70 76 | 0 77 | 9 78 | $MIRRTEXT 79 | 70 80 | 0 81 | 9 82 | $LTSCALE 83 | 40 84 | 1.0 85 | 9 86 | $ATTMODE 87 | 70 88 | 1 89 | 9 90 | $TEXTSIZE 91 | 40 92 | 0.1875 93 | 9 94 | $TRACEWID 95 | 40 96 | 0.05 97 | 9 98 | $TEXTSTYLE 99 | 7 100 | FG-Title 101 | 9 102 | $CLAYER 103 | 8 104 | FG-Dtl-Hidden 105 | 9 106 | $CELTYPE 107 | 6 108 | ByLayer 109 | 9 110 | $CECOLOR 111 | 62 112 | 256 113 | 9 114 | $CELTSCALE 115 | 40 116 | 1.0 117 | 9 118 | $DISPSILH 119 | 70 120 | 1 121 | 9 122 | $DIMSCALE 123 | 40 124 | 48.0 125 | 9 126 | $DIMASZ 127 | 40 128 | 0.125 129 | 9 130 | $DIMEXO 131 | 40 132 | 0.0625 133 | 9 134 | $DIMDLI 135 | 40 136 | 0.375 137 | 9 138 | $DIMRND 139 | 40 140 | 0.0 141 | 9 142 | $DIMDLE 143 | 40 144 | 0.0 145 | 9 146 | $DIMEXE 147 | 40 148 | 0.0625 149 | 9 150 | $DIMTP 151 | 40 152 | 0.0 153 | 9 154 | $DIMTM 155 | 40 156 | 0.0 157 | 9 158 | $DIMTXT 159 | 40 160 | 0.09375 161 | 9 162 | $DIMCEN 163 | 40 164 | 0.09 165 | 9 166 | $DIMTSZ 167 | 40 168 | 0.0 169 | 9 170 | $DIMTOL 171 | 70 172 | 0 173 | 9 174 | $DIMLIM 175 | 70 176 | 0 177 | 9 178 | $DIMTIH 179 | 70 180 | 0 181 | 9 182 | $DIMTOH 183 | 70 184 | 0 185 | 9 186 | $DIMSE1 187 | 70 188 | 0 189 | 9 190 | $DIMSE2 191 | 70 192 | 0 193 | 9 194 | $DIMTAD 195 | 70 196 | 1 197 | 9 198 | $DIMZIN 199 | 70 200 | 0 201 | 9 202 | $DIMBLK 203 | 1 204 | Oblique 205 | 9 206 | $DIMASO 207 | 70 208 | 1 209 | 9 210 | $DIMSHO 211 | 70 212 | 1 213 | 9 214 | $DIMPOST 215 | 1 216 | " 217 | 9 218 | $DIMAPOST 219 | 1 220 | 221 | 9 222 | $DIMALT 223 | 70 224 | 0 225 | 9 226 | $DIMALTD 227 | 70 228 | 4 229 | 9 230 | $DIMALTF 231 | 40 232 | 1.0 233 | 9 234 | $DIMLFAC 235 | 40 236 | 1.0 237 | 9 238 | $DIMTOFL 239 | 70 240 | 1 241 | 9 242 | $DIMTVP 243 | 40 244 | 0.0 245 | 9 246 | $DIMTIX 247 | 70 248 | 0 249 | 9 250 | $DIMSOXD 251 | 70 252 | 0 253 | 9 254 | $DIMSAH 255 | 70 256 | 0 257 | 9 258 | $DIMBLK1 259 | 1 260 | 261 | 9 262 | $DIMBLK2 263 | 1 264 | 265 | 9 266 | $DIMSTYLE 267 | 2 268 | STANDARD 269 | 9 270 | $DIMCLRD 271 | 70 272 | 256 273 | 9 274 | $DIMCLRE 275 | 70 276 | 256 277 | 9 278 | $DIMCLRT 279 | 70 280 | 256 281 | 9 282 | $DIMTFAC 283 | 40 284 | 1.0 285 | 9 286 | $DIMGAP 287 | 40 288 | 0.03125 289 | 9 290 | $DIMJUST 291 | 70 292 | 0 293 | 9 294 | $DIMSD1 295 | 70 296 | 0 297 | 9 298 | $DIMSD2 299 | 70 300 | 0 301 | 9 302 | $DIMTOLJ 303 | 70 304 | 1 305 | 9 306 | $DIMTZIN 307 | 70 308 | 0 309 | 9 310 | $DIMALTZ 311 | 70 312 | 0 313 | 9 314 | $DIMALTTZ 315 | 70 316 | 0 317 | 9 318 | $DIMUPT 319 | 70 320 | 0 321 | 9 322 | $DIMDEC 323 | 70 324 | 4 325 | 9 326 | $DIMTDEC 327 | 70 328 | 4 329 | 9 330 | $DIMALTU 331 | 70 332 | 6 333 | 9 334 | $DIMALTTD 335 | 70 336 | 4 337 | 9 338 | $DIMTXSTY 339 | 7 340 | FG-Note 341 | 9 342 | $DIMAUNIT 343 | 70 344 | 0 345 | 9 346 | $DIMADEC 347 | 70 348 | 0 349 | 9 350 | $DIMALTRND 351 | 40 352 | 0.0 353 | 9 354 | $DIMAZIN 355 | 70 356 | 0 357 | 9 358 | $DIMDSEP 359 | 70 360 | 46 361 | 9 362 | $DIMATFIT 363 | 70 364 | 0 365 | 9 366 | $DIMFRAC 367 | 70 368 | 1 369 | 9 370 | $DIMLDRBLK 371 | 1 372 | 373 | 9 374 | $DIMLUNIT 375 | 70 376 | 5 377 | 9 378 | $DIMLWD 379 | 70 380 | -1 381 | 9 382 | $DIMLWE 383 | 70 384 | -1 385 | 9 386 | $DIMTMOVE 387 | 70 388 | 0 389 | 9 390 | $DIMFXL 391 | 40 392 | 0.18 393 | 9 394 | $DIMFXLON 395 | 70 396 | 0 397 | 9 398 | $DIMJOGANG 399 | 40 400 | 0.7853981633974483 401 | 9 402 | $DIMTFILL 403 | 70 404 | 0 405 | 9 406 | $DIMTFILLCLR 407 | 70 408 | 0 409 | 9 410 | $DIMARCSYM 411 | 70 412 | 0 413 | 9 414 | $DIMLTYPE 415 | 6 416 | ByLayer 417 | 9 418 | $DIMLTEX1 419 | 6 420 | ByLayer 421 | 9 422 | $DIMLTEX2 423 | 6 424 | ByLayer 425 | 9 426 | $DIMTXTDIRECTION 427 | 70 428 | 0 429 | 9 430 | $LUNITS 431 | 70 432 | 2 433 | 9 434 | $LUPREC 435 | 70 436 | 5 437 | 9 438 | $SKETCHINC 439 | 40 440 | 0.1 441 | 9 442 | $FILLETRAD 443 | 40 444 | 0.0 445 | 9 446 | $AUNITS 447 | 70 448 | 0 449 | 9 450 | $AUPREC 451 | 70 452 | 0 453 | 9 454 | $MENU 455 | 1 456 | . 457 | 9 458 | $ELEVATION 459 | 40 460 | 0.0 461 | 9 462 | $PELEVATION 463 | 40 464 | 0.0 465 | 9 466 | $THICKNESS 467 | 40 468 | 0.0 469 | 9 470 | $LIMCHECK 471 | 70 472 | 0 473 | 9 474 | $CHAMFERA 475 | 40 476 | 0.0 477 | 9 478 | $CHAMFERB 479 | 40 480 | 0.0 481 | 9 482 | $CHAMFERC 483 | 40 484 | 0.0 485 | 9 486 | $CHAMFERD 487 | 40 488 | 0.0 489 | 9 490 | $SKPOLY 491 | 70 492 | 0 493 | 9 494 | $TDCREATE 495 | 40 496 | 2455379.770598715 497 | 9 498 | $TDUCREATE 499 | 40 500 | 2455379.770598715 501 | 9 502 | $TDUPDATE 503 | 40 504 | 2455614.973897338 505 | 9 506 | $TDUUPDATE 507 | 40 508 | 2455614.973897338 509 | 9 510 | $TDINDWG 511 | 40 512 | 1.6838402431 513 | 9 514 | $TDUSRTIMER 515 | 40 516 | 1.6838402431 517 | 9 518 | $USRTIMER 519 | 70 520 | 1 521 | 9 522 | $ANGBASE 523 | 50 524 | 0.0 525 | 9 526 | $ANGDIR 527 | 70 528 | 0 529 | 9 530 | $PDMODE 531 | 70 532 | 0 533 | 9 534 | $PDSIZE 535 | 40 536 | 0.0 537 | 9 538 | $PLINEWID 539 | 40 540 | 0.0 541 | 9 542 | $SPLFRAME 543 | 70 544 | 0 545 | 9 546 | $SPLINETYPE 547 | 70 548 | 6 549 | 9 550 | $SPLINESEGS 551 | 70 552 | 8 553 | 9 554 | $HANDSEED 555 | 5 556 | BFA8 557 | 9 558 | $SURFTAB1 559 | 70 560 | 6 561 | 9 562 | $SURFTAB2 563 | 70 564 | 6 565 | 9 566 | $SURFTYPE 567 | 70 568 | 6 569 | 9 570 | $SURFU 571 | 70 572 | 6 573 | 9 574 | $SURFV 575 | 70 576 | 6 577 | 9 578 | $UCSBASE 579 | 2 580 | 581 | 9 582 | $UCSNAME 583 | 2 584 | 585 | 9 586 | $UCSORG 587 | 10 588 | 0.0 589 | 20 590 | 0.0 591 | 30 592 | 0.0 593 | 9 594 | $UCSXDIR 595 | 10 596 | 1.0 597 | 20 598 | 0.0 599 | 30 600 | 0.0 601 | 9 602 | $UCSYDIR 603 | 10 604 | 0.0 605 | 20 606 | 1.0 607 | 30 608 | 0.0 609 | 9 610 | $UCSORTHOREF 611 | 2 612 | 613 | 9 614 | $UCSORTHOVIEW 615 | 70 616 | 0 617 | 9 618 | $UCSORGTOP 619 | 10 620 | 0.0 621 | 20 622 | 0.0 623 | 30 624 | 0.0 625 | 9 626 | $UCSORGBOTTOM 627 | 10 628 | 0.0 629 | 20 630 | 0.0 631 | 30 632 | 0.0 633 | 9 634 | $UCSORGLEFT 635 | 10 636 | 0.0 637 | 20 638 | 0.0 639 | 30 640 | 0.0 641 | 9 642 | $UCSORGRIGHT 643 | 10 644 | 0.0 645 | 20 646 | 0.0 647 | 30 648 | 0.0 649 | 9 650 | $UCSORGFRONT 651 | 10 652 | 0.0 653 | 20 654 | 0.0 655 | 30 656 | 0.0 657 | 9 658 | $UCSORGBACK 659 | 10 660 | 0.0 661 | 20 662 | 0.0 663 | 30 664 | 0.0 665 | 9 666 | $PUCSBASE 667 | 2 668 | 669 | 9 670 | $PUCSNAME 671 | 2 672 | 673 | 9 674 | $PUCSORG 675 | 10 676 | 0.0 677 | 20 678 | 0.0 679 | 30 680 | 0.0 681 | 9 682 | $PUCSXDIR 683 | 10 684 | 1.0 685 | 20 686 | 0.0 687 | 30 688 | 0.0 689 | 9 690 | $PUCSYDIR 691 | 10 692 | 0.0 693 | 20 694 | 1.0 695 | 30 696 | 0.0 697 | 9 698 | $PUCSORTHOREF 699 | 2 700 | 701 | 9 702 | $PUCSORTHOVIEW 703 | 70 704 | 0 705 | 9 706 | $PUCSORGTOP 707 | 10 708 | 0.0 709 | 20 710 | 0.0 711 | 30 712 | 0.0 713 | 9 714 | $PUCSORGBOTTOM 715 | 10 716 | 0.0 717 | 20 718 | 0.0 719 | 30 720 | 0.0 721 | 9 722 | $PUCSORGLEFT 723 | 10 724 | 0.0 725 | 20 726 | 0.0 727 | 30 728 | 0.0 729 | 9 730 | $PUCSORGRIGHT 731 | 10 732 | 0.0 733 | 20 734 | 0.0 735 | 30 736 | 0.0 737 | 9 738 | $PUCSORGFRONT 739 | 10 740 | 0.0 741 | 20 742 | 0.0 743 | 30 744 | 0.0 745 | 9 746 | $PUCSORGBACK 747 | 10 748 | 0.0 749 | 20 750 | 0.0 751 | 30 752 | 0.0 753 | 9 754 | $USERI1 755 | 70 756 | 0 757 | 9 758 | $USERI2 759 | 70 760 | 0 761 | 9 762 | $USERI3 763 | 70 764 | 0 765 | 9 766 | $USERI4 767 | 70 768 | 0 769 | 9 770 | $USERI5 771 | 70 772 | 0 773 | 9 774 | $USERR1 775 | 40 776 | 0.0 777 | 9 778 | $USERR2 779 | 40 780 | 0.0 781 | 9 782 | $USERR3 783 | 40 784 | 0.0 785 | 9 786 | $USERR4 787 | 40 788 | 0.0 789 | 9 790 | $USERR5 791 | 40 792 | 0.0 793 | 9 794 | $WORLDVIEW 795 | 70 796 | 1 797 | 9 798 | $SHADEDGE 799 | 70 800 | 3 801 | 9 802 | $SHADEDIF 803 | 70 804 | 70 805 | 9 806 | $TILEMODE 807 | 70 808 | 0 809 | 9 810 | $MAXACTVP 811 | 70 812 | 64 813 | 9 814 | $PINSBASE 815 | 10 816 | 0.0 817 | 20 818 | 0.0 819 | 30 820 | 0.0 821 | 9 822 | $PLIMCHECK 823 | 70 824 | 0 825 | 9 826 | $PEXTMIN 827 | 10 828 | -0.25 829 | 20 830 | -0.1305130401371635 831 | 30 832 | 0.0 833 | 9 834 | $PEXTMAX 835 | 10 836 | 16.5 837 | 20 838 | 10.61948695986283 839 | 30 840 | 0.0 841 | 9 842 | $PLIMMIN 843 | 10 844 | -0.2499321702471884 845 | 20 846 | -0.3750450970290743 847 | 9 848 | $PLIMMAX 849 | 10 850 | 16.75006734916103 851 | 20 852 | 10.62495466267503 853 | 9 854 | $UNITMODE 855 | 70 856 | 0 857 | 9 858 | $VISRETAIN 859 | 70 860 | 1 861 | 9 862 | $PLINEGEN 863 | 70 864 | 0 865 | 9 866 | $PSLTSCALE 867 | 70 868 | 1 869 | 9 870 | $TREEDEPTH 871 | 70 872 | 3020 873 | 9 874 | $CMLSTYLE 875 | 2 876 | Standard 877 | 9 878 | $CMLJUST 879 | 70 880 | 0 881 | 9 882 | $CMLSCALE 883 | 40 884 | 1.0 885 | 9 886 | $PROXYGRAPHICS 887 | 70 888 | 1 889 | 9 890 | $MEASUREMENT 891 | 70 892 | 0 893 | 9 894 | $CELWEIGHT 895 | 370 896 | -1 897 | 9 898 | $ENDCAPS 899 | 280 900 | 0 901 | 9 902 | $JOINSTYLE 903 | 280 904 | 0 905 | 9 906 | $LWDISPLAY 907 | 290 908 | 0 909 | 9 910 | $INSUNITS 911 | 70 912 | 0 913 | 9 914 | $HYPERLINKBASE 915 | 1 916 | 917 | 9 918 | $STYLESHEET 919 | 1 920 | Florida.ctb 921 | 9 922 | $XEDIT 923 | 290 924 | 1 925 | 9 926 | $CEPSNTYPE 927 | 380 928 | 0 929 | 9 930 | $PSTYLEMODE 931 | 290 932 | 1 933 | 9 934 | $FINGERPRINTGUID 935 | 2 936 | {E451773B-08B1-4376-9DA5-8F5F0D6C19EA} 937 | 9 938 | $VERSIONGUID 939 | 2 940 | {6EFBAB5D-9128-4E51-B2D4-822E03762ACA} 941 | 9 942 | $EXTNAMES 943 | 290 944 | 1 945 | 9 946 | $PSVPSCALE 947 | 40 948 | 0.0 949 | 9 950 | $OLESTARTUP 951 | 290 952 | 0 953 | 9 954 | $SORTENTS 955 | 280 956 | 127 957 | 9 958 | $INDEXCTL 959 | 280 960 | 0 961 | 9 962 | $HIDETEXT 963 | 280 964 | 1 965 | 9 966 | $XCLIPFRAME 967 | 280 968 | 0 969 | 9 970 | $HALOGAP 971 | 280 972 | 0 973 | 9 974 | $OBSCOLOR 975 | 70 976 | 257 977 | 9 978 | $OBSLTYPE 979 | 280 980 | 0 981 | 9 982 | $INTERSECTIONDISPLAY 983 | 280 984 | 0 985 | 9 986 | $INTERSECTIONCOLOR 987 | 70 988 | 257 989 | 9 990 | $DIMASSOC 991 | 280 992 | 2 993 | 9 994 | $PROJECTNAME 995 | 1 996 | 997 | 9 998 | $CAMERADISPLAY 999 | 290 1000 | 0 1001 | 9 1002 | $LENSLENGTH 1003 | 40 1004 | 50.0 1005 | 9 1006 | $CAMERAHEIGHT 1007 | 40 1008 | 0.0 1009 | 9 1010 | $STEPSPERSEC 1011 | 40 1012 | 2.0 1013 | 9 1014 | $STEPSIZE 1015 | 40 1016 | 6.0 1017 | 9 1018 | $3DDWFPREC 1019 | 40 1020 | 2.0 1021 | 9 1022 | $PSOLWIDTH 1023 | 40 1024 | 0.25 1025 | 9 1026 | $PSOLHEIGHT 1027 | 40 1028 | 4.0 1029 | 9 1030 | $LOFTANG1 1031 | 40 1032 | 1.570796326794896 1033 | 9 1034 | $LOFTANG2 1035 | 40 1036 | 1.570796326794896 1037 | 9 1038 | $LOFTMAG1 1039 | 40 1040 | 0.0 1041 | 9 1042 | $LOFTMAG2 1043 | 40 1044 | 0.0 1045 | 9 1046 | $LOFTPARAM 1047 | 70 1048 | 7 1049 | 9 1050 | $LOFTNORMALS 1051 | 280 1052 | 1 1053 | 9 1054 | $LATITUDE 1055 | 40 1056 | 37.795 1057 | 9 1058 | $LONGITUDE 1059 | 40 1060 | -122.394 1061 | 9 1062 | $NORTHDIRECTION 1063 | 40 1064 | 0.0 1065 | 9 1066 | $TIMEZONE 1067 | 70 1068 | -8000 1069 | 9 1070 | $LIGHTGLYPHDISPLAY 1071 | 280 1072 | 1 1073 | 9 1074 | $TILEMODELIGHTSYNCH 1075 | 280 1076 | 1 1077 | 9 1078 | $CMATERIAL 1079 | 347 1080 | 96 1081 | 9 1082 | $SOLIDHIST 1083 | 280 1084 | 0 1085 | 9 1086 | $SHOWHIST 1087 | 280 1088 | 1 1089 | 9 1090 | $DWFFRAME 1091 | 280 1092 | 2 1093 | 9 1094 | $DGNFRAME 1095 | 280 1096 | 0 1097 | 9 1098 | $REALWORLDSCALE 1099 | 290 1100 | 1 1101 | 9 1102 | $INTERFERECOLOR 1103 | 62 1104 | 1 1105 | 9 1106 | $INTERFEREOBJVS 1107 | 345 1108 | A3 1109 | 9 1110 | $INTERFEREVPVS 1111 | 346 1112 | BF84 1113 | 9 1114 | $CSHADOW 1115 | 280 1116 | 0 1117 | 9 1118 | $SHADOWPLANELOCATION 1119 | 40 1120 | 0.0 1121 | 0 1122 | ENDSEC 1123 | 0 1124 | EOF -------------------------------------------------------------------------------- /test/data/header.parser.out: -------------------------------------------------------------------------------- 1 | { 2 | "header": { 3 | "$ACADVER": "AC1027", 4 | "$ACADMAINTVER": 55, 5 | "$DWGCODEPAGE": "ANSI_1252", 6 | "$LASTSAVEDBY": "Shane", 7 | "$REQUIREDVERSIONS": 0, 8 | "$INSBASE": { 9 | "x": 0, 10 | "y": 0, 11 | "z": 0 12 | }, 13 | "$EXTMIN": { 14 | "x": 146.8403717847312, 15 | "y": 141.8294137695975, 16 | "z": -5.934454319554902 17 | }, 18 | "$EXTMAX": { 19 | "x": 762.6679804989191, 20 | "y": 545.821967323924, 21 | "z": 6.065545680445099 22 | }, 23 | "$LIMMIN": { 24 | "x": 0, 25 | "y": 0 26 | }, 27 | "$LIMMAX": { 28 | "x": 1000, 29 | "y": 800 30 | }, 31 | "$ORTHOMODE": 1, 32 | "$REGENMODE": 1, 33 | "$FILLMODE": 1, 34 | "$QTEXTMODE": 0, 35 | "$MIRRTEXT": 0, 36 | "$LTSCALE": 1, 37 | "$ATTMODE": 1, 38 | "$TEXTSIZE": 0.1875, 39 | "$TRACEWID": 0.05, 40 | "$TEXTSTYLE": "FG-Title", 41 | "$CLAYER": "FG-Dtl-Hidden", 42 | "$CELTYPE": "ByLayer", 43 | "$CECOLOR": 256, 44 | "$CELTSCALE": 1, 45 | "$DISPSILH": 1, 46 | "$DIMSCALE": 48, 47 | "$DIMASZ": 0.125, 48 | "$DIMEXO": 0.0625, 49 | "$DIMDLI": 0.375, 50 | "$DIMRND": 0, 51 | "$DIMDLE": 0, 52 | "$DIMEXE": 0.0625, 53 | "$DIMTP": 0, 54 | "$DIMTM": 0, 55 | "$DIMTXT": 0.09375, 56 | "$DIMCEN": 0.09, 57 | "$DIMTSZ": 0, 58 | "$DIMTOL": 0, 59 | "$DIMLIM": 0, 60 | "$DIMTIH": 0, 61 | "$DIMTOH": 0, 62 | "$DIMSE1": 0, 63 | "$DIMSE2": 0, 64 | "$DIMTAD": 1, 65 | "$DIMZIN": 0, 66 | "$DIMBLK": "Oblique", 67 | "$DIMASO": 1, 68 | "$DIMSHO": 1, 69 | "$DIMPOST": "\"", 70 | "$DIMAPOST": "", 71 | "$DIMALT": 0, 72 | "$DIMALTD": 4, 73 | "$DIMALTF": 1, 74 | "$DIMLFAC": 1, 75 | "$DIMTOFL": 1, 76 | "$DIMTVP": 0, 77 | "$DIMTIX": 0, 78 | "$DIMSOXD": 0, 79 | "$DIMSAH": 0, 80 | "$DIMBLK1": "", 81 | "$DIMBLK2": "", 82 | "$DIMSTYLE": "STANDARD", 83 | "$DIMCLRD": 256, 84 | "$DIMCLRE": 256, 85 | "$DIMCLRT": 256, 86 | "$DIMTFAC": 1, 87 | "$DIMGAP": 0.03125, 88 | "$DIMJUST": 0, 89 | "$DIMSD1": 0, 90 | "$DIMSD2": 0, 91 | "$DIMTOLJ": 1, 92 | "$DIMTZIN": 0, 93 | "$DIMALTZ": 0, 94 | "$DIMALTTZ": 0, 95 | "$DIMUPT": 0, 96 | "$DIMDEC": 4, 97 | "$DIMTDEC": 4, 98 | "$DIMALTU": 6, 99 | "$DIMALTTD": 4, 100 | "$DIMTXSTY": "FG-Note", 101 | "$DIMAUNIT": 0, 102 | "$DIMADEC": 0, 103 | "$DIMALTRND": 0, 104 | "$DIMAZIN": 0, 105 | "$DIMDSEP": 46, 106 | "$DIMATFIT": 0, 107 | "$DIMFRAC": 1, 108 | "$DIMLDRBLK": "", 109 | "$DIMLUNIT": 5, 110 | "$DIMLWD": -1, 111 | "$DIMLWE": -1, 112 | "$DIMTMOVE": 0, 113 | "$DIMFXL": 0.18, 114 | "$DIMFXLON": 0, 115 | "$DIMJOGANG": 0.7853981633974483, 116 | "$DIMTFILL": 0, 117 | "$DIMTFILLCLR": 0, 118 | "$DIMARCSYM": 0, 119 | "$DIMLTYPE": "ByLayer", 120 | "$DIMLTEX1": "ByLayer", 121 | "$DIMLTEX2": "ByLayer", 122 | "$DIMTXTDIRECTION": 0, 123 | "$LUNITS": 2, 124 | "$LUPREC": 5, 125 | "$SKETCHINC": 0.1, 126 | "$FILLETRAD": 0, 127 | "$AUNITS": 0, 128 | "$AUPREC": 0, 129 | "$MENU": ".", 130 | "$ELEVATION": 0, 131 | "$PELEVATION": 0, 132 | "$THICKNESS": 0, 133 | "$LIMCHECK": 0, 134 | "$CHAMFERA": 0, 135 | "$CHAMFERB": 0, 136 | "$CHAMFERC": 0, 137 | "$CHAMFERD": 0, 138 | "$SKPOLY": 0, 139 | "$TDCREATE": 2455379.770598715, 140 | "$TDUCREATE": 2455379.770598715, 141 | "$TDUPDATE": 2455614.973897338, 142 | "$TDUUPDATE": 2455614.973897338, 143 | "$TDINDWG": 1.6838402431, 144 | "$TDUSRTIMER": 1.6838402431, 145 | "$USRTIMER": 1, 146 | "$ANGBASE": 0, 147 | "$ANGDIR": 0, 148 | "$PDMODE": 0, 149 | "$PDSIZE": 0, 150 | "$PLINEWID": 0, 151 | "$SPLFRAME": 0, 152 | "$SPLINETYPE": 6, 153 | "$SPLINESEGS": 8, 154 | "$HANDSEED": "BFA8", 155 | "$SURFTAB1": 6, 156 | "$SURFTAB2": 6, 157 | "$SURFTYPE": 6, 158 | "$SURFU": 6, 159 | "$SURFV": 6, 160 | "$UCSBASE": "", 161 | "$UCSNAME": "", 162 | "$UCSORG": { 163 | "x": 0, 164 | "y": 0, 165 | "z": 0 166 | }, 167 | "$UCSXDIR": { 168 | "x": 1, 169 | "y": 0, 170 | "z": 0 171 | }, 172 | "$UCSYDIR": { 173 | "x": 0, 174 | "y": 1, 175 | "z": 0 176 | }, 177 | "$UCSORTHOREF": "", 178 | "$UCSORTHOVIEW": 0, 179 | "$UCSORGTOP": { 180 | "x": 0, 181 | "y": 0, 182 | "z": 0 183 | }, 184 | "$UCSORGBOTTOM": { 185 | "x": 0, 186 | "y": 0, 187 | "z": 0 188 | }, 189 | "$UCSORGLEFT": { 190 | "x": 0, 191 | "y": 0, 192 | "z": 0 193 | }, 194 | "$UCSORGRIGHT": { 195 | "x": 0, 196 | "y": 0, 197 | "z": 0 198 | }, 199 | "$UCSORGFRONT": { 200 | "x": 0, 201 | "y": 0, 202 | "z": 0 203 | }, 204 | "$UCSORGBACK": { 205 | "x": 0, 206 | "y": 0, 207 | "z": 0 208 | }, 209 | "$PUCSBASE": "", 210 | "$PUCSNAME": "", 211 | "$PUCSORG": { 212 | "x": 0, 213 | "y": 0, 214 | "z": 0 215 | }, 216 | "$PUCSXDIR": { 217 | "x": 1, 218 | "y": 0, 219 | "z": 0 220 | }, 221 | "$PUCSYDIR": { 222 | "x": 0, 223 | "y": 1, 224 | "z": 0 225 | }, 226 | "$PUCSORTHOREF": "", 227 | "$PUCSORTHOVIEW": 0, 228 | "$PUCSORGTOP": { 229 | "x": 0, 230 | "y": 0, 231 | "z": 0 232 | }, 233 | "$PUCSORGBOTTOM": { 234 | "x": 0, 235 | "y": 0, 236 | "z": 0 237 | }, 238 | "$PUCSORGLEFT": { 239 | "x": 0, 240 | "y": 0, 241 | "z": 0 242 | }, 243 | "$PUCSORGRIGHT": { 244 | "x": 0, 245 | "y": 0, 246 | "z": 0 247 | }, 248 | "$PUCSORGFRONT": { 249 | "x": 0, 250 | "y": 0, 251 | "z": 0 252 | }, 253 | "$PUCSORGBACK": { 254 | "x": 0, 255 | "y": 0, 256 | "z": 0 257 | }, 258 | "$USERI1": 0, 259 | "$USERI2": 0, 260 | "$USERI3": 0, 261 | "$USERI4": 0, 262 | "$USERI5": 0, 263 | "$USERR1": 0, 264 | "$USERR2": 0, 265 | "$USERR3": 0, 266 | "$USERR4": 0, 267 | "$USERR5": 0, 268 | "$WORLDVIEW": 1, 269 | "$SHADEDGE": 3, 270 | "$SHADEDIF": 70, 271 | "$TILEMODE": 0, 272 | "$MAXACTVP": 64, 273 | "$PINSBASE": { 274 | "x": 0, 275 | "y": 0, 276 | "z": 0 277 | }, 278 | "$PLIMCHECK": 0, 279 | "$PEXTMIN": { 280 | "x": -0.25, 281 | "y": -0.1305130401371635, 282 | "z": 0 283 | }, 284 | "$PEXTMAX": { 285 | "x": 16.5, 286 | "y": 10.61948695986283, 287 | "z": 0 288 | }, 289 | "$PLIMMIN": { 290 | "x": -0.2499321702471884, 291 | "y": -0.3750450970290743 292 | }, 293 | "$PLIMMAX": { 294 | "x": 16.75006734916103, 295 | "y": 10.62495466267503 296 | }, 297 | "$UNITMODE": 0, 298 | "$VISRETAIN": 1, 299 | "$PLINEGEN": 0, 300 | "$PSLTSCALE": 1, 301 | "$TREEDEPTH": 3020, 302 | "$CMLSTYLE": "Standard", 303 | "$CMLJUST": 0, 304 | "$CMLSCALE": 1, 305 | "$PROXYGRAPHICS": 1, 306 | "$MEASUREMENT": 0, 307 | "$CELWEIGHT": -1, 308 | "$ENDCAPS": 0, 309 | "$JOINSTYLE": 0, 310 | "$LWDISPLAY": false, 311 | "$INSUNITS": 0, 312 | "$HYPERLINKBASE": "", 313 | "$STYLESHEET": "Florida.ctb", 314 | "$XEDIT": true, 315 | "$CEPSNTYPE": 0, 316 | "$PSTYLEMODE": true, 317 | "$FINGERPRINTGUID": "{E451773B-08B1-4376-9DA5-8F5F0D6C19EA}", 318 | "$VERSIONGUID": "{6EFBAB5D-9128-4E51-B2D4-822E03762ACA}", 319 | "$EXTNAMES": true, 320 | "$PSVPSCALE": 0, 321 | "$OLESTARTUP": false, 322 | "$SORTENTS": 127, 323 | "$INDEXCTL": 0, 324 | "$HIDETEXT": 1, 325 | "$XCLIPFRAME": 0, 326 | "$HALOGAP": 0, 327 | "$OBSCOLOR": 257, 328 | "$OBSLTYPE": 0, 329 | "$INTERSECTIONDISPLAY": 0, 330 | "$INTERSECTIONCOLOR": 257, 331 | "$DIMASSOC": 2, 332 | "$PROJECTNAME": "", 333 | "$CAMERADISPLAY": false, 334 | "$LENSLENGTH": 50, 335 | "$CAMERAHEIGHT": 0, 336 | "$STEPSPERSEC": 2, 337 | "$STEPSIZE": 6, 338 | "$3DDWFPREC": 2, 339 | "$PSOLWIDTH": 0.25, 340 | "$PSOLHEIGHT": 4, 341 | "$LOFTANG1": 1.570796326794896, 342 | "$LOFTANG2": 1.570796326794896, 343 | "$LOFTMAG1": 0, 344 | "$LOFTMAG2": 0, 345 | "$LOFTPARAM": 7, 346 | "$LOFTNORMALS": 1, 347 | "$LATITUDE": 37.795, 348 | "$LONGITUDE": -122.394, 349 | "$NORTHDIRECTION": 0, 350 | "$TIMEZONE": -8000, 351 | "$LIGHTGLYPHDISPLAY": 1, 352 | "$TILEMODELIGHTSYNCH": 1, 353 | "$CMATERIAL": "96", 354 | "$SOLIDHIST": 0, 355 | "$SHOWHIST": 1, 356 | "$DWFFRAME": 2, 357 | "$DGNFRAME": 0, 358 | "$REALWORLDSCALE": true, 359 | "$INTERFERECOLOR": 1, 360 | "$INTERFEREOBJVS": "A3", 361 | "$INTERFEREVPVS": "BF84", 362 | "$CSHADOW": 0, 363 | "$SHADOWPLANELOCATION": 0 364 | } 365 | } -------------------------------------------------------------------------------- /test/data/header.scanner.out: -------------------------------------------------------------------------------- 1 | [{"code":0,"value":"SECTION"},{"code":2,"value":"HEADER"},{"code":9,"value":"$ACADVER"},{"code":1,"value":"AC1027"},{"code":9,"value":"$ACADMAINTVER"},{"code":70,"value":55},{"code":9,"value":"$DWGCODEPAGE"},{"code":3,"value":"ANSI_1252"},{"code":9,"value":"$LASTSAVEDBY"},{"code":1,"value":"Shane"},{"code":9,"value":"$REQUIREDVERSIONS"},{"code":160,"value":0},{"code":9,"value":"$INSBASE"},{"code":10,"value":0},{"code":20,"value":0},{"code":30,"value":0},{"code":9,"value":"$EXTMIN"},{"code":10,"value":146.8403717847312},{"code":20,"value":141.8294137695975},{"code":30,"value":-5.934454319554902},{"code":9,"value":"$EXTMAX"},{"code":10,"value":762.6679804989191},{"code":20,"value":545.821967323924},{"code":30,"value":6.065545680445099},{"code":9,"value":"$LIMMIN"},{"code":10,"value":0},{"code":20,"value":0},{"code":9,"value":"$LIMMAX"},{"code":10,"value":1000},{"code":20,"value":800},{"code":9,"value":"$ORTHOMODE"},{"code":70,"value":1},{"code":9,"value":"$REGENMODE"},{"code":70,"value":1},{"code":9,"value":"$FILLMODE"},{"code":70,"value":1},{"code":9,"value":"$QTEXTMODE"},{"code":70,"value":0},{"code":9,"value":"$MIRRTEXT"},{"code":70,"value":0},{"code":9,"value":"$LTSCALE"},{"code":40,"value":1},{"code":9,"value":"$ATTMODE"},{"code":70,"value":1},{"code":9,"value":"$TEXTSIZE"},{"code":40,"value":0.1875},{"code":9,"value":"$TRACEWID"},{"code":40,"value":0.05},{"code":9,"value":"$TEXTSTYLE"},{"code":7,"value":"FG-Title"},{"code":9,"value":"$CLAYER"},{"code":8,"value":"FG-Dtl-Hidden"},{"code":9,"value":"$CELTYPE"},{"code":6,"value":"ByLayer"},{"code":9,"value":"$CECOLOR"},{"code":62,"value":256},{"code":9,"value":"$CELTSCALE"},{"code":40,"value":1},{"code":9,"value":"$DISPSILH"},{"code":70,"value":1},{"code":9,"value":"$DIMSCALE"},{"code":40,"value":48},{"code":9,"value":"$DIMASZ"},{"code":40,"value":0.125},{"code":9,"value":"$DIMEXO"},{"code":40,"value":0.0625},{"code":9,"value":"$DIMDLI"},{"code":40,"value":0.375},{"code":9,"value":"$DIMRND"},{"code":40,"value":0},{"code":9,"value":"$DIMDLE"},{"code":40,"value":0},{"code":9,"value":"$DIMEXE"},{"code":40,"value":0.0625},{"code":9,"value":"$DIMTP"},{"code":40,"value":0},{"code":9,"value":"$DIMTM"},{"code":40,"value":0},{"code":9,"value":"$DIMTXT"},{"code":40,"value":0.09375},{"code":9,"value":"$DIMCEN"},{"code":40,"value":0.09},{"code":9,"value":"$DIMTSZ"},{"code":40,"value":0},{"code":9,"value":"$DIMTOL"},{"code":70,"value":0},{"code":9,"value":"$DIMLIM"},{"code":70,"value":0},{"code":9,"value":"$DIMTIH"},{"code":70,"value":0},{"code":9,"value":"$DIMTOH"},{"code":70,"value":0},{"code":9,"value":"$DIMSE1"},{"code":70,"value":0},{"code":9,"value":"$DIMSE2"},{"code":70,"value":0},{"code":9,"value":"$DIMTAD"},{"code":70,"value":1},{"code":9,"value":"$DIMZIN"},{"code":70,"value":0},{"code":9,"value":"$DIMBLK"},{"code":1,"value":"Oblique"},{"code":9,"value":"$DIMASO"},{"code":70,"value":1},{"code":9,"value":"$DIMSHO"},{"code":70,"value":1},{"code":9,"value":"$DIMPOST"},{"code":1,"value":"\""},{"code":9,"value":"$DIMAPOST"},{"code":1,"value":""},{"code":9,"value":"$DIMALT"},{"code":70,"value":0},{"code":9,"value":"$DIMALTD"},{"code":70,"value":4},{"code":9,"value":"$DIMALTF"},{"code":40,"value":1},{"code":9,"value":"$DIMLFAC"},{"code":40,"value":1},{"code":9,"value":"$DIMTOFL"},{"code":70,"value":1},{"code":9,"value":"$DIMTVP"},{"code":40,"value":0},{"code":9,"value":"$DIMTIX"},{"code":70,"value":0},{"code":9,"value":"$DIMSOXD"},{"code":70,"value":0},{"code":9,"value":"$DIMSAH"},{"code":70,"value":0},{"code":9,"value":"$DIMBLK1"},{"code":1,"value":""},{"code":9,"value":"$DIMBLK2"},{"code":1,"value":""},{"code":9,"value":"$DIMSTYLE"},{"code":2,"value":"STANDARD"},{"code":9,"value":"$DIMCLRD"},{"code":70,"value":256},{"code":9,"value":"$DIMCLRE"},{"code":70,"value":256},{"code":9,"value":"$DIMCLRT"},{"code":70,"value":256},{"code":9,"value":"$DIMTFAC"},{"code":40,"value":1},{"code":9,"value":"$DIMGAP"},{"code":40,"value":0.03125},{"code":9,"value":"$DIMJUST"},{"code":70,"value":0},{"code":9,"value":"$DIMSD1"},{"code":70,"value":0},{"code":9,"value":"$DIMSD2"},{"code":70,"value":0},{"code":9,"value":"$DIMTOLJ"},{"code":70,"value":1},{"code":9,"value":"$DIMTZIN"},{"code":70,"value":0},{"code":9,"value":"$DIMALTZ"},{"code":70,"value":0},{"code":9,"value":"$DIMALTTZ"},{"code":70,"value":0},{"code":9,"value":"$DIMUPT"},{"code":70,"value":0},{"code":9,"value":"$DIMDEC"},{"code":70,"value":4},{"code":9,"value":"$DIMTDEC"},{"code":70,"value":4},{"code":9,"value":"$DIMALTU"},{"code":70,"value":6},{"code":9,"value":"$DIMALTTD"},{"code":70,"value":4},{"code":9,"value":"$DIMTXSTY"},{"code":7,"value":"FG-Note"},{"code":9,"value":"$DIMAUNIT"},{"code":70,"value":0},{"code":9,"value":"$DIMADEC"},{"code":70,"value":0},{"code":9,"value":"$DIMALTRND"},{"code":40,"value":0},{"code":9,"value":"$DIMAZIN"},{"code":70,"value":0},{"code":9,"value":"$DIMDSEP"},{"code":70,"value":46},{"code":9,"value":"$DIMATFIT"},{"code":70,"value":0},{"code":9,"value":"$DIMFRAC"},{"code":70,"value":1},{"code":9,"value":"$DIMLDRBLK"},{"code":1,"value":""},{"code":9,"value":"$DIMLUNIT"},{"code":70,"value":5},{"code":9,"value":"$DIMLWD"},{"code":70,"value":-1},{"code":9,"value":"$DIMLWE"},{"code":70,"value":-1},{"code":9,"value":"$DIMTMOVE"},{"code":70,"value":0},{"code":9,"value":"$DIMFXL"},{"code":40,"value":0.18},{"code":9,"value":"$DIMFXLON"},{"code":70,"value":0},{"code":9,"value":"$DIMJOGANG"},{"code":40,"value":0.7853981633974483},{"code":9,"value":"$DIMTFILL"},{"code":70,"value":0},{"code":9,"value":"$DIMTFILLCLR"},{"code":70,"value":0},{"code":9,"value":"$DIMARCSYM"},{"code":70,"value":0},{"code":9,"value":"$DIMLTYPE"},{"code":6,"value":"ByLayer"},{"code":9,"value":"$DIMLTEX1"},{"code":6,"value":"ByLayer"},{"code":9,"value":"$DIMLTEX2"},{"code":6,"value":"ByLayer"},{"code":9,"value":"$DIMTXTDIRECTION"},{"code":70,"value":0},{"code":9,"value":"$LUNITS"},{"code":70,"value":2},{"code":9,"value":"$LUPREC"},{"code":70,"value":5},{"code":9,"value":"$SKETCHINC"},{"code":40,"value":0.1},{"code":9,"value":"$FILLETRAD"},{"code":40,"value":0},{"code":9,"value":"$AUNITS"},{"code":70,"value":0},{"code":9,"value":"$AUPREC"},{"code":70,"value":0},{"code":9,"value":"$MENU"},{"code":1,"value":"."},{"code":9,"value":"$ELEVATION"},{"code":40,"value":0},{"code":9,"value":"$PELEVATION"},{"code":40,"value":0},{"code":9,"value":"$THICKNESS"},{"code":40,"value":0},{"code":9,"value":"$LIMCHECK"},{"code":70,"value":0},{"code":9,"value":"$CHAMFERA"},{"code":40,"value":0},{"code":9,"value":"$CHAMFERB"},{"code":40,"value":0},{"code":9,"value":"$CHAMFERC"},{"code":40,"value":0},{"code":9,"value":"$CHAMFERD"},{"code":40,"value":0},{"code":9,"value":"$SKPOLY"},{"code":70,"value":0},{"code":9,"value":"$TDCREATE"},{"code":40,"value":2455379.770598715},{"code":9,"value":"$TDUCREATE"},{"code":40,"value":2455379.770598715},{"code":9,"value":"$TDUPDATE"},{"code":40,"value":2455614.973897338},{"code":9,"value":"$TDUUPDATE"},{"code":40,"value":2455614.973897338},{"code":9,"value":"$TDINDWG"},{"code":40,"value":1.6838402431},{"code":9,"value":"$TDUSRTIMER"},{"code":40,"value":1.6838402431},{"code":9,"value":"$USRTIMER"},{"code":70,"value":1},{"code":9,"value":"$ANGBASE"},{"code":50,"value":0},{"code":9,"value":"$ANGDIR"},{"code":70,"value":0},{"code":9,"value":"$PDMODE"},{"code":70,"value":0},{"code":9,"value":"$PDSIZE"},{"code":40,"value":0},{"code":9,"value":"$PLINEWID"},{"code":40,"value":0},{"code":9,"value":"$SPLFRAME"},{"code":70,"value":0},{"code":9,"value":"$SPLINETYPE"},{"code":70,"value":6},{"code":9,"value":"$SPLINESEGS"},{"code":70,"value":8},{"code":9,"value":"$HANDSEED"},{"code":5,"value":"BFA8"},{"code":9,"value":"$SURFTAB1"},{"code":70,"value":6},{"code":9,"value":"$SURFTAB2"},{"code":70,"value":6},{"code":9,"value":"$SURFTYPE"},{"code":70,"value":6},{"code":9,"value":"$SURFU"},{"code":70,"value":6},{"code":9,"value":"$SURFV"},{"code":70,"value":6},{"code":9,"value":"$UCSBASE"},{"code":2,"value":""},{"code":9,"value":"$UCSNAME"},{"code":2,"value":""},{"code":9,"value":"$UCSORG"},{"code":10,"value":0},{"code":20,"value":0},{"code":30,"value":0},{"code":9,"value":"$UCSXDIR"},{"code":10,"value":1},{"code":20,"value":0},{"code":30,"value":0},{"code":9,"value":"$UCSYDIR"},{"code":10,"value":0},{"code":20,"value":1},{"code":30,"value":0},{"code":9,"value":"$UCSORTHOREF"},{"code":2,"value":""},{"code":9,"value":"$UCSORTHOVIEW"},{"code":70,"value":0},{"code":9,"value":"$UCSORGTOP"},{"code":10,"value":0},{"code":20,"value":0},{"code":30,"value":0},{"code":9,"value":"$UCSORGBOTTOM"},{"code":10,"value":0},{"code":20,"value":0},{"code":30,"value":0},{"code":9,"value":"$UCSORGLEFT"},{"code":10,"value":0},{"code":20,"value":0},{"code":30,"value":0},{"code":9,"value":"$UCSORGRIGHT"},{"code":10,"value":0},{"code":20,"value":0},{"code":30,"value":0},{"code":9,"value":"$UCSORGFRONT"},{"code":10,"value":0},{"code":20,"value":0},{"code":30,"value":0},{"code":9,"value":"$UCSORGBACK"},{"code":10,"value":0},{"code":20,"value":0},{"code":30,"value":0},{"code":9,"value":"$PUCSBASE"},{"code":2,"value":""},{"code":9,"value":"$PUCSNAME"},{"code":2,"value":""},{"code":9,"value":"$PUCSORG"},{"code":10,"value":0},{"code":20,"value":0},{"code":30,"value":0},{"code":9,"value":"$PUCSXDIR"},{"code":10,"value":1},{"code":20,"value":0},{"code":30,"value":0},{"code":9,"value":"$PUCSYDIR"},{"code":10,"value":0},{"code":20,"value":1},{"code":30,"value":0},{"code":9,"value":"$PUCSORTHOREF"},{"code":2,"value":""},{"code":9,"value":"$PUCSORTHOVIEW"},{"code":70,"value":0},{"code":9,"value":"$PUCSORGTOP"},{"code":10,"value":0},{"code":20,"value":0},{"code":30,"value":0},{"code":9,"value":"$PUCSORGBOTTOM"},{"code":10,"value":0},{"code":20,"value":0},{"code":30,"value":0},{"code":9,"value":"$PUCSORGLEFT"},{"code":10,"value":0},{"code":20,"value":0},{"code":30,"value":0},{"code":9,"value":"$PUCSORGRIGHT"},{"code":10,"value":0},{"code":20,"value":0},{"code":30,"value":0},{"code":9,"value":"$PUCSORGFRONT"},{"code":10,"value":0},{"code":20,"value":0},{"code":30,"value":0},{"code":9,"value":"$PUCSORGBACK"},{"code":10,"value":0},{"code":20,"value":0},{"code":30,"value":0},{"code":9,"value":"$USERI1"},{"code":70,"value":0},{"code":9,"value":"$USERI2"},{"code":70,"value":0},{"code":9,"value":"$USERI3"},{"code":70,"value":0},{"code":9,"value":"$USERI4"},{"code":70,"value":0},{"code":9,"value":"$USERI5"},{"code":70,"value":0},{"code":9,"value":"$USERR1"},{"code":40,"value":0},{"code":9,"value":"$USERR2"},{"code":40,"value":0},{"code":9,"value":"$USERR3"},{"code":40,"value":0},{"code":9,"value":"$USERR4"},{"code":40,"value":0},{"code":9,"value":"$USERR5"},{"code":40,"value":0},{"code":9,"value":"$WORLDVIEW"},{"code":70,"value":1},{"code":9,"value":"$SHADEDGE"},{"code":70,"value":3},{"code":9,"value":"$SHADEDIF"},{"code":70,"value":70},{"code":9,"value":"$TILEMODE"},{"code":70,"value":0},{"code":9,"value":"$MAXACTVP"},{"code":70,"value":64},{"code":9,"value":"$PINSBASE"},{"code":10,"value":0},{"code":20,"value":0},{"code":30,"value":0},{"code":9,"value":"$PLIMCHECK"},{"code":70,"value":0},{"code":9,"value":"$PEXTMIN"},{"code":10,"value":-0.25},{"code":20,"value":-0.1305130401371635},{"code":30,"value":0},{"code":9,"value":"$PEXTMAX"},{"code":10,"value":16.5},{"code":20,"value":10.61948695986283},{"code":30,"value":0},{"code":9,"value":"$PLIMMIN"},{"code":10,"value":-0.2499321702471884},{"code":20,"value":-0.3750450970290743},{"code":9,"value":"$PLIMMAX"},{"code":10,"value":16.75006734916103},{"code":20,"value":10.62495466267503},{"code":9,"value":"$UNITMODE"},{"code":70,"value":0},{"code":9,"value":"$VISRETAIN"},{"code":70,"value":1},{"code":9,"value":"$PLINEGEN"},{"code":70,"value":0},{"code":9,"value":"$PSLTSCALE"},{"code":70,"value":1},{"code":9,"value":"$TREEDEPTH"},{"code":70,"value":3020},{"code":9,"value":"$CMLSTYLE"},{"code":2,"value":"Standard"},{"code":9,"value":"$CMLJUST"},{"code":70,"value":0},{"code":9,"value":"$CMLSCALE"},{"code":40,"value":1},{"code":9,"value":"$PROXYGRAPHICS"},{"code":70,"value":1},{"code":9,"value":"$MEASUREMENT"},{"code":70,"value":0},{"code":9,"value":"$CELWEIGHT"},{"code":370,"value":-1},{"code":9,"value":"$ENDCAPS"},{"code":280,"value":0},{"code":9,"value":"$JOINSTYLE"},{"code":280,"value":0},{"code":9,"value":"$LWDISPLAY"},{"code":290,"value":false},{"code":9,"value":"$INSUNITS"},{"code":70,"value":0},{"code":9,"value":"$HYPERLINKBASE"},{"code":1,"value":""},{"code":9,"value":"$STYLESHEET"},{"code":1,"value":"Florida.ctb"},{"code":9,"value":"$XEDIT"},{"code":290,"value":true},{"code":9,"value":"$CEPSNTYPE"},{"code":380,"value":0},{"code":9,"value":"$PSTYLEMODE"},{"code":290,"value":true},{"code":9,"value":"$FINGERPRINTGUID"},{"code":2,"value":"{E451773B-08B1-4376-9DA5-8F5F0D6C19EA}"},{"code":9,"value":"$VERSIONGUID"},{"code":2,"value":"{6EFBAB5D-9128-4E51-B2D4-822E03762ACA}"},{"code":9,"value":"$EXTNAMES"},{"code":290,"value":true},{"code":9,"value":"$PSVPSCALE"},{"code":40,"value":0},{"code":9,"value":"$OLESTARTUP"},{"code":290,"value":false},{"code":9,"value":"$SORTENTS"},{"code":280,"value":127},{"code":9,"value":"$INDEXCTL"},{"code":280,"value":0},{"code":9,"value":"$HIDETEXT"},{"code":280,"value":1},{"code":9,"value":"$XCLIPFRAME"},{"code":280,"value":0},{"code":9,"value":"$HALOGAP"},{"code":280,"value":0},{"code":9,"value":"$OBSCOLOR"},{"code":70,"value":257},{"code":9,"value":"$OBSLTYPE"},{"code":280,"value":0},{"code":9,"value":"$INTERSECTIONDISPLAY"},{"code":280,"value":0},{"code":9,"value":"$INTERSECTIONCOLOR"},{"code":70,"value":257},{"code":9,"value":"$DIMASSOC"},{"code":280,"value":2},{"code":9,"value":"$PROJECTNAME"},{"code":1,"value":""},{"code":9,"value":"$CAMERADISPLAY"},{"code":290,"value":false},{"code":9,"value":"$LENSLENGTH"},{"code":40,"value":50},{"code":9,"value":"$CAMERAHEIGHT"},{"code":40,"value":0},{"code":9,"value":"$STEPSPERSEC"},{"code":40,"value":2},{"code":9,"value":"$STEPSIZE"},{"code":40,"value":6},{"code":9,"value":"$3DDWFPREC"},{"code":40,"value":2},{"code":9,"value":"$PSOLWIDTH"},{"code":40,"value":0.25},{"code":9,"value":"$PSOLHEIGHT"},{"code":40,"value":4},{"code":9,"value":"$LOFTANG1"},{"code":40,"value":1.570796326794896},{"code":9,"value":"$LOFTANG2"},{"code":40,"value":1.570796326794896},{"code":9,"value":"$LOFTMAG1"},{"code":40,"value":0},{"code":9,"value":"$LOFTMAG2"},{"code":40,"value":0},{"code":9,"value":"$LOFTPARAM"},{"code":70,"value":7},{"code":9,"value":"$LOFTNORMALS"},{"code":280,"value":1},{"code":9,"value":"$LATITUDE"},{"code":40,"value":37.795},{"code":9,"value":"$LONGITUDE"},{"code":40,"value":-122.394},{"code":9,"value":"$NORTHDIRECTION"},{"code":40,"value":0},{"code":9,"value":"$TIMEZONE"},{"code":70,"value":-8000},{"code":9,"value":"$LIGHTGLYPHDISPLAY"},{"code":280,"value":1},{"code":9,"value":"$TILEMODELIGHTSYNCH"},{"code":280,"value":1},{"code":9,"value":"$CMATERIAL"},{"code":347,"value":"96"},{"code":9,"value":"$SOLIDHIST"},{"code":280,"value":0},{"code":9,"value":"$SHOWHIST"},{"code":280,"value":1},{"code":9,"value":"$DWFFRAME"},{"code":280,"value":2},{"code":9,"value":"$DGNFRAME"},{"code":280,"value":0},{"code":9,"value":"$REALWORLDSCALE"},{"code":290,"value":true},{"code":9,"value":"$INTERFERECOLOR"},{"code":62,"value":1},{"code":9,"value":"$INTERFEREOBJVS"},{"code":345,"value":"A3"},{"code":9,"value":"$INTERFEREVPVS"},{"code":346,"value":"BF84"},{"code":9,"value":"$CSHADOW"},{"code":280,"value":0},{"code":9,"value":"$SHADOWPLANELOCATION"},{"code":40,"value":0},{"code":0,"value":"ENDSEC"},{"code":0,"value":"EOF"}] -------------------------------------------------------------------------------- /test/data/layer-table.expected.json: -------------------------------------------------------------------------------- 1 | { 2 | "handle": "2", 3 | "ownerHandle": "0", 4 | "layers": { 5 | "0": { 6 | "frozen": false, 7 | "name": "0", 8 | "visible": true, 9 | "colorIndex": 7, 10 | "color": 16777215 11 | }, 12 | "Layer 1": { 13 | "frozen": true, 14 | "name": "Layer 1", 15 | "visible": true, 16 | "colorIndex": 7, 17 | "color": 16777215 18 | } 19 | } 20 | } -------------------------------------------------------------------------------- /test/data/ltype-table.expected.json: -------------------------------------------------------------------------------- 1 | { 2 | "handle": "5", 3 | "ownerHandle": "0", 4 | "lineTypes": { 5 | "ByBlock": { 6 | "name": "ByBlock", 7 | "description": "", 8 | "patternLength": 0 9 | }, 10 | "ByLayer": { 11 | "name": "ByLayer", 12 | "description": "", 13 | "patternLength": 0 14 | }, 15 | "Continuous": { 16 | "name": "Continuous", 17 | "description": "Solid line", 18 | "patternLength": 0 19 | }, 20 | "PHANTOM2": { 21 | "name": "PHANTOM2", 22 | "description": "Phantom (.5x) ___ _ _ ___ _ _ ___ _ _ ___ _ _", 23 | "pattern": [ 24 | 0.625, 25 | -0.125, 26 | 0.125, 27 | -0.125, 28 | 0.125, 29 | -0.125 30 | ], 31 | "patternLength": 1.25 32 | }, 33 | "CENTER1": { 34 | "name": "CENTER1", 35 | "description": "Center (.5x) ___ _ ___ _ ___ _ ___ _ ___ _ ___", 36 | "pattern": [ 37 | 0.75, 38 | -0.125, 39 | 0.125, 40 | -0.125 41 | ], 42 | "patternLength": 1.125 43 | }, 44 | "CENTER2": { 45 | "name": "CENTER2", 46 | "description": "Center (2x) ________ __ ________ __ _____", 47 | "pattern": [ 48 | 2.5, 49 | -0.5, 50 | 0.5, 51 | -0.5 52 | ], 53 | "patternLength": 4 54 | }, 55 | "DASHDOT1": { 56 | "name": "DASHDOT1", 57 | "description": "Dash dot (.5x) _._._._._._._._._._._._._._._.", 58 | "pattern": [ 59 | 0.25, 60 | -0.125, 61 | 0, 62 | -0.125 63 | ], 64 | "patternLength": 0.5 65 | }, 66 | "DASHDOT2": { 67 | "name": "DASHDOT2", 68 | "description": "Dash dot (2x) ____ . ____ . ____ . ___", 69 | "pattern": [ 70 | 1, 71 | -0.5, 72 | 0, 73 | -0.5 74 | ], 75 | "patternLength": 2 76 | }, 77 | "DASHED1": { 78 | "name": "DASHED1", 79 | "description": "Dashed (.5x) _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _", 80 | "pattern": [ 81 | 0.25, 82 | -0.125 83 | ], 84 | "patternLength": 0.375 85 | }, 86 | "DASHED2": { 87 | "name": "DASHED2", 88 | "description": "Dashed (2x) ____ ____ ____ ____ ____ ___", 89 | "pattern": [ 90 | 1, 91 | -0.5 92 | ], 93 | "patternLength": 1.5 94 | }, 95 | "DOT1": { 96 | "name": "DOT1", 97 | "description": "Dot (.5x) .....................................", 98 | "pattern": [ 99 | 0, 100 | -0.125 101 | ], 102 | "patternLength": 0.125 103 | }, 104 | "DOT2": { 105 | "name": "DOT2", 106 | "description": "Dot (2x) . . . . . . . . . . . . .", 107 | "pattern": [ 108 | 0, 109 | -0.5 110 | ], 111 | "patternLength": 0.5 112 | } 113 | } 114 | } -------------------------------------------------------------------------------- /test/data/mleader.approved.txt: -------------------------------------------------------------------------------- 1 | { 2 | "entities": [ 3 | { 4 | "arrowHeadSize": 350, 5 | "blockAttributeId": "1F", 6 | "blockContentColor": -1056964608, 7 | "blockContentConnectionType": 0, 8 | "blockContentRotation": 0, 9 | "blockContentScale": { 10 | "x": 1, 11 | "y": 1, 12 | "z": 1 13 | }, 14 | "contentType": 2, 15 | "contextData": { 16 | "arrowHeadSize": 350, 17 | "contentBasePosition": { 18 | "x": 7132.85123236126, 19 | "y": -1009.033075955183, 20 | "z": 0 21 | }, 22 | "contentScale": 100, 23 | "defaultTextContents": "I am curvy leader ?", 24 | "hasBlock": false, 25 | "hasMText": true, 26 | "landingGap": 100, 27 | "leaders": [ 28 | { 29 | "doglegLength": 0, 30 | "doglegVector": { 31 | "x": 1, 32 | "y": 0, 33 | "z": 0 34 | }, 35 | "hasSetDoglegVector": true, 36 | "hasSetLastLeaderLinePoint": true, 37 | "lastLeaderLinePoint": { 38 | "x": 7132.85123236126, 39 | "y": -1009.033075955183, 40 | "z": 0 41 | }, 42 | "leaderBranchIndex": 0, 43 | "leaderLines": [ 44 | { 45 | "vertices": [ 46 | [ 47 | { 48 | "x": 175.8864995559104, 49 | "y": -69.50729210365648, 50 | "z": 0 51 | }, 52 | { 53 | "x": 242.9954841167346, 54 | "y": -2306.473444131101, 55 | "z": 0 56 | }, 57 | { 58 | "x": 2726.027912867196, 59 | "y": -2888.084643658236, 60 | "z": 0 61 | }, 62 | { 63 | "x": 4202.42557320531, 64 | "y": -1299.838675718751, 65 | "z": 0 66 | } 67 | ] 68 | ] 69 | } 70 | ] 71 | } 72 | ], 73 | "planeNormalReversed": false, 74 | "planeOriginPoint": { 75 | "x": 0, 76 | "y": 0, 77 | "z": 0 78 | }, 79 | "planeXAxisDirection": { 80 | "x": 1, 81 | "y": 0, 82 | "z": 0 83 | }, 84 | "planeYAxisDirection": { 85 | "x": 0, 86 | "y": 1, 87 | "z": 0 88 | }, 89 | "textAttachment": 1, 90 | "textBackgroundColorOn": false, 91 | "textBackgroundFillOn": false, 92 | "textBackgroundScaleFactor": 1.5, 93 | "textBackgroundTransparency": 0, 94 | "textColor": -939524096, 95 | "textColumnGutterWidth": 0, 96 | "textColumnType": 0, 97 | "textColumnWidth": 0, 98 | "textDirection": { 99 | "x": 1, 100 | "y": 0, 101 | "z": 0 102 | }, 103 | "textFlowDirection": 1, 104 | "textHeight": 0, 105 | "textLineSpacingFactor": 1, 106 | "textLineSpacingStyle": 1, 107 | "textLocation": { 108 | "x": 7232.85123236126, 109 | "y": -782.7580759551835, 110 | "z": 0 111 | }, 112 | "textNormalDirection": { 113 | "x": 0, 114 | "y": 0, 115 | "z": 1 116 | }, 117 | "textRotation": 0, 118 | "textUseAutoHeight": false, 119 | "textUseWordBreak": false, 120 | "textWidth": 0 121 | }, 122 | "doglegLength": 0, 123 | "enableAnotationScale": false, 124 | "enableDogLeg": false, 125 | "enableFrameText": false, 126 | "enableLanding": false, 127 | "extendedData": { 128 | "applicationName": "ACAD_MLEADERVER" 129 | }, 130 | "handle": "62", 131 | "layer": "Default", 132 | "leaderLineColor": -1056964608, 133 | "leaderLineType": 1, 134 | "leaderLineTypeId": "14", 135 | "leaderLineWeight": -2, 136 | "leaderStyleId": "61", 137 | "textAlignInIPE": 0, 138 | "textAlignmentType": 0, 139 | "textAngleType": 2, 140 | "textAttachmentPoint": 1, 141 | "textColor": -939524096, 142 | "textDirectionNegative": false, 143 | "textLeftAttachmentType": 1, 144 | "textStyleId": "60", 145 | "type": "MULTILEADER" 146 | }, 147 | { 148 | "arrowHeadSize": 350, 149 | "blockAttributeId": "1F", 150 | "blockContentColor": -1056964608, 151 | "blockContentConnectionType": 0, 152 | "blockContentRotation": 0, 153 | "blockContentScale": { 154 | "x": 1, 155 | "y": 1, 156 | "z": 1 157 | }, 158 | "contentType": 2, 159 | "contextData": { 160 | "arrowHeadSize": 350, 161 | "contentBasePosition": { 162 | "x": 6320.904102092164, 163 | "y": 2833.188934631764, 164 | "z": 0 165 | }, 166 | "contentScale": 100, 167 | "defaultTextContents": "I am leader too", 168 | "hasBlock": false, 169 | "hasMText": true, 170 | "landingGap": 100, 171 | "leaders": [ 172 | { 173 | "doglegLength": 0, 174 | "doglegVector": { 175 | "x": 1, 176 | "y": 0, 177 | "z": 0 178 | }, 179 | "hasSetDoglegVector": true, 180 | "hasSetLastLeaderLinePoint": true, 181 | "lastLeaderLinePoint": { 182 | "x": 6320.904102092164, 183 | "y": 2833.188934631764, 184 | "z": 0 185 | }, 186 | "leaderBranchIndex": 0, 187 | "leaderLines": [ 188 | { 189 | "vertices": [ 190 | [ 191 | { 192 | "x": 2328.832202913205, 193 | "y": 749.092575501571, 194 | "z": 0 195 | }, 196 | { 197 | "x": 3282.819972937589, 198 | "y": 3244.137512488422, 199 | "z": 0 200 | }, 201 | { 202 | "x": 4398.251827119944, 203 | "y": 2114.028923382613, 204 | "z": 0 205 | }, 206 | { 207 | "x": 4809.200404976602, 208 | "y": 3567.025680804367, 209 | "z": 0 210 | }, 211 | { 212 | "x": 5792.541644847891, 213 | "y": 2833.188934631764, 214 | "z": 0 215 | } 216 | ] 217 | ] 218 | } 219 | ] 220 | } 221 | ], 222 | "planeNormalReversed": false, 223 | "planeOriginPoint": { 224 | "x": 0, 225 | "y": 0, 226 | "z": 0 227 | }, 228 | "planeXAxisDirection": { 229 | "x": 1, 230 | "y": 0, 231 | "z": 0 232 | }, 233 | "planeYAxisDirection": { 234 | "x": 0, 235 | "y": 1, 236 | "z": 0 237 | }, 238 | "textAttachment": 1, 239 | "textBackgroundColorOn": false, 240 | "textBackgroundFillOn": false, 241 | "textBackgroundScaleFactor": 1.5, 242 | "textBackgroundTransparency": 0, 243 | "textColor": -939524096, 244 | "textColumnGutterWidth": 0, 245 | "textColumnType": 0, 246 | "textColumnWidth": 0, 247 | "textDirection": { 248 | "x": 1, 249 | "y": 0, 250 | "z": 0 251 | }, 252 | "textFlowDirection": 1, 253 | "textHeight": 0, 254 | "textLineSpacingFactor": 1, 255 | "textLineSpacingStyle": 1, 256 | "textLocation": { 257 | "x": 6420.904102092164, 258 | "y": 3010.988934631764, 259 | "z": 0 260 | }, 261 | "textNormalDirection": { 262 | "x": 0, 263 | "y": 0, 264 | "z": 1 265 | }, 266 | "textRotation": 0, 267 | "textUseAutoHeight": false, 268 | "textUseWordBreak": false, 269 | "textWidth": 0 270 | }, 271 | "doglegLength": 0, 272 | "enableAnotationScale": false, 273 | "enableDogLeg": false, 274 | "enableFrameText": false, 275 | "enableLanding": false, 276 | "extendedData": { 277 | "applicationName": "ACAD_MLEADERVER" 278 | }, 279 | "handle": "63", 280 | "layer": "Default", 281 | "leaderLineColor": -1056964608, 282 | "leaderLineType": 1, 283 | "leaderLineTypeId": "14", 284 | "leaderLineWeight": -2, 285 | "leaderStyleId": "61", 286 | "textAlignInIPE": 0, 287 | "textAlignmentType": 0, 288 | "textAngleType": 2, 289 | "textAttachmentPoint": 1, 290 | "textColor": -939524096, 291 | "textDirectionNegative": false, 292 | "textLeftAttachmentType": 1, 293 | "textStyleId": "60", 294 | "type": "MULTILEADER" 295 | }, 296 | { 297 | "arrowHeadSize": 350, 298 | "blockAttributeId": "1F", 299 | "blockContentColor": -1056964608, 300 | "blockContentConnectionType": 0, 301 | "blockContentRotation": 0, 302 | "blockContentScale": { 303 | "x": 1, 304 | "y": 1, 305 | "z": 1 306 | }, 307 | "contentType": 2, 308 | "contextData": { 309 | "arrowHeadSize": 350, 310 | "contentBasePosition": { 311 | "x": -3005.890492848878, 312 | "y": 3229.460777564969, 313 | "z": 0 314 | }, 315 | "contentScale": 100, 316 | "defaultTextContents": "I am leader", 317 | "hasBlock": false, 318 | "hasMText": true, 319 | "landingGap": 100, 320 | "leaders": [ 321 | { 322 | "doglegLength": 0, 323 | "doglegVector": { 324 | "x": -1, 325 | "y": 0, 326 | "z": 0 327 | }, 328 | "hasSetDoglegVector": true, 329 | "hasSetLastLeaderLinePoint": true, 330 | "lastLeaderLinePoint": { 331 | "x": -401.0404928488783, 332 | "y": 3229.460777564969, 333 | "z": 0 334 | }, 335 | "leaderBranchIndex": 0, 336 | "leaderLines": [ 337 | { 338 | "vertices": [ 339 | [ 340 | { 341 | "x": 1477.581577352986, 342 | "y": 778.4460453484751, 343 | "z": 0 344 | }, 345 | { 346 | "x": 787.7750359507374, 347 | "y": 3229.460777564969, 348 | "z": 0 349 | } 350 | ] 351 | ] 352 | } 353 | ] 354 | } 355 | ], 356 | "planeNormalReversed": false, 357 | "planeOriginPoint": { 358 | "x": 0, 359 | "y": 0, 360 | "z": 0 361 | }, 362 | "planeXAxisDirection": { 363 | "x": 1, 364 | "y": 0, 365 | "z": 0 366 | }, 367 | "planeYAxisDirection": { 368 | "x": 0, 369 | "y": 1, 370 | "z": 0 371 | }, 372 | "textAttachment": 1, 373 | "textBackgroundColorOn": false, 374 | "textBackgroundFillOn": false, 375 | "textBackgroundScaleFactor": 1.5, 376 | "textBackgroundTransparency": 0, 377 | "textColor": -939524096, 378 | "textColumnGutterWidth": 0, 379 | "textColumnType": 0, 380 | "textColumnWidth": 0, 381 | "textDirection": { 382 | "x": 1, 383 | "y": 0, 384 | "z": 0 385 | }, 386 | "textFlowDirection": 1, 387 | "textHeight": 0, 388 | "textLineSpacingFactor": 1, 389 | "textLineSpacingStyle": 1, 390 | "textLocation": { 391 | "x": -2905.890492848878, 392 | "y": 3407.260777564969, 393 | "z": 0 394 | }, 395 | "textNormalDirection": { 396 | "x": 0, 397 | "y": 0, 398 | "z": 1 399 | }, 400 | "textRotation": 0, 401 | "textUseAutoHeight": false, 402 | "textUseWordBreak": false, 403 | "textWidth": 0 404 | }, 405 | "doglegLength": 0, 406 | "enableAnotationScale": false, 407 | "enableDogLeg": false, 408 | "enableFrameText": false, 409 | "enableLanding": false, 410 | "extendedData": { 411 | "applicationName": "ACAD_MLEADERVER" 412 | }, 413 | "handle": "64", 414 | "layer": "Default", 415 | "leaderLineColor": -1056964608, 416 | "leaderLineType": 1, 417 | "leaderLineTypeId": "14", 418 | "leaderLineWeight": -2, 419 | "leaderStyleId": "61", 420 | "textAlignInIPE": 0, 421 | "textAlignmentType": 0, 422 | "textAngleType": 2, 423 | "textAttachmentPoint": 1, 424 | "textColor": -939524096, 425 | "textDirectionNegative": false, 426 | "textLeftAttachmentType": 1, 427 | "textStyleId": "60", 428 | "type": "MULTILEADER" 429 | } 430 | ] 431 | } 432 | -------------------------------------------------------------------------------- /test/data/mleader.dxf: -------------------------------------------------------------------------------- 1 | 0 2 | SECTION 3 | 2 4 | ENTITIES 5 | 0 6 | MULTILEADER 7 | 5 8 | 62 9 | 330 10 | 1F 11 | 100 12 | AcDbEntity 13 | 8 14 | Default 15 | 92 16 | 576 17 | 310 18 | 400200000B0000000C00000013000000993A00000C0000000E00000001010000E800000026000000E9305DEA5913BC4063FADC11D5CA91C0000000000000000000000000000000000000000000000000000000000000F03F000000000000F03F000000000000000000000000000000004900200061006D0020006300750072 19 | 310 20 | 007600790020006C006500610064006500720020003F00000013000000010000000000000000E07540000000000000F03F0000000000000000000000000000F03F00000000000000000000000000000000000000000000000000000000010000000000000041007200690061006C00000061007200690061006C002E007400 21 | 310 22 | 740066000000000000000C00000013000000112700000C00000013000000010000000C0000000E000000120000000C00000016000000000000C20C0000001400000001000000540000000700000003000000F63A66C0630260406E2BCDF595517AC00000000000000000B81151345EFC654050AE4C79776051C00000000000 23 | 310 24 | 000000EEC9834B0B966E40A4D831689C197AC000000000000000000C00000013000000891300009C00000020000000050000007202F585374C67400882FF2E99357AC0000000000000000000A28101DB5F6E4020E74467F204A2C000000000000000007E67984A0E4CA540E0DF69562B90A6C00000000000000000DC965DF2 25 | 310 26 | 6C6AB040F2BFCECD5A4F94C00000000000000000E9305DEAD9DCBB40608E53BD43888FC0000000000000000000000000000000000000000000000000000000000000F03F 27 | 100 28 | AcDbMLeader 29 | 300 30 | CONTEXT_DATA{ 31 | 40 32 | 100.0 33 | 10 34 | 7132.85123236126 35 | 20 36 | -1009.033075955183 37 | 30 38 | 0.0 39 | 41 40 | 350.0 41 | 140 42 | 350.0 43 | 145 44 | 100.0 45 | 174 46 | 1 47 | 175 48 | 1 49 | 176 50 | 0 51 | 177 52 | 0 53 | 290 54 | 1 55 | 304 56 | I am curvy leader ? 57 | 11 58 | 0.0 59 | 21 60 | 0.0 61 | 31 62 | 1.0 63 | 340 64 | 60 65 | 12 66 | 7232.85123236126 67 | 22 68 | -782.7580759551835 69 | 32 70 | 0.0 71 | 13 72 | 1.0 73 | 23 74 | 0.0 75 | 33 76 | 0.0 77 | 42 78 | 0.0 79 | 43 80 | 0.0 81 | 44 82 | 0.0 83 | 45 84 | 1.0 85 | 170 86 | 1 87 | 90 88 | -939524096 89 | 171 90 | 1 91 | 172 92 | 1 93 | 91 94 | -939524096 95 | 141 96 | 1.5 97 | 92 98 | 0 99 | 291 100 | 0 101 | 292 102 | 0 103 | 173 104 | 0 105 | 293 106 | 0 107 | 142 108 | 0.0 109 | 143 110 | 0.0 111 | 294 112 | 0 113 | 295 114 | 0 115 | 296 116 | 0 117 | 110 118 | 0.0 119 | 120 120 | 0.0 121 | 130 122 | 0.0 123 | 111 124 | 1.0 125 | 121 126 | 0.0 127 | 131 128 | 0.0 129 | 112 130 | 0.0 131 | 122 132 | 1.0 133 | 132 134 | 0.0 135 | 297 136 | 0 137 | 302 138 | LEADER{ 139 | 290 140 | 1 141 | 291 142 | 1 143 | 10 144 | 7132.85123236126 145 | 20 146 | -1009.033075955183 147 | 30 148 | 0.0 149 | 11 150 | 1.0 151 | 21 152 | 0.0 153 | 31 154 | 0.0 155 | 90 156 | 0 157 | 40 158 | 0.0 159 | 304 160 | LEADER_LINE{ 161 | 10 162 | 175.8864995559104 163 | 20 164 | -69.50729210365648 165 | 30 166 | 0.0 167 | 10 168 | 242.9954841167346 169 | 20 170 | -2306.473444131101 171 | 30 172 | 0.0 173 | 10 174 | 2726.027912867196 175 | 20 176 | -2888.084643658236 177 | 30 178 | 0.0 179 | 10 180 | 4202.42557320531 181 | 20 182 | -1299.838675718751 183 | 30 184 | 0.0 185 | 91 186 | 0 187 | 305 188 | } 189 | 303 190 | } 191 | 301 192 | } 193 | 340 194 | 61 195 | 90 196 | 50657520 197 | 170 198 | 1 199 | 91 200 | -1056964608 201 | 341 202 | 14 203 | 171 204 | -2 205 | 290 206 | 0 207 | 291 208 | 0 209 | 41 210 | 0.0 211 | 42 212 | 350.0 213 | 172 214 | 2 215 | 343 216 | 60 217 | 173 218 | 1 219 | 95 220 | 1 221 | 174 222 | 2 223 | 175 224 | 0 225 | 92 226 | -939524096 227 | 292 228 | 0 229 | 93 230 | -1056964608 231 | 10 232 | 1.0 233 | 20 234 | 1.0 235 | 30 236 | 1.0 237 | 43 238 | 0.0 239 | 176 240 | 0 241 | 293 242 | 0 243 | 294 244 | 0 245 | 178 246 | 0 247 | 179 248 | 1 249 | 45 250 | 100.0 251 | 1001 252 | ACAD_MLEADERVER 253 | 1070 254 | 2 255 | 0 256 | MULTILEADER 257 | 5 258 | 63 259 | 330 260 | 1F 261 | 100 262 | AcDbEntity 263 | 8 264 | Default 265 | 92 266 | 592 267 | 310 268 | 500200000B0000000C00000013000000993A00000C0000000E00000001010000E00000002600000017163C7367E7B8409EDAA355FAC9A440000000000000000000000000000000000000000000000000000000000000F03F000000000000F03F000000000000000000000000000000004900200061006D0020006C00650061 269 | 310 270 | 00640065007200200074006F006F0000000F000000010000000000000000E07540000000000000F03F0000000000000000000000000000F03F00000000000000000000000000000000000000000000000000000000010000000000000041007200690061006C00000061007200690061006C002E0074007400660000000000 271 | 310 272 | 00000C00000013000000112700000C00000013000000010000000C0000000E000000120000000C00000016000000000000C20C00000014000000010000005400000007000000030000004753FB22A298A3408BE0AEF6B57C90400000000000000000B30F8016AA31A240447D3998BD6887400000000000000000F757671BB0 273 | 310 274 | BEA2407E647AFC5F23914000000000000000000C0000001300000089130000B400000020000000060000009E55311FA92BA34085A294F90AD090400000000000000000192D7ED3A3A5A940207109684658A940000000000000000068FCBD77402EB140D3AC0BCF0E84A04000000000000000007694BD4D33C9B240C8CD0826 275 | 310 276 | 0DDEAB400000000000000000BD9B3CA98AA0B64004410ABC6022A640000000000000000017163C73E7B0B84004410ABC6022A640000000000000000000000000000000000000000000000000000000000000F03F 277 | 100 278 | AcDbMLeader 279 | 300 280 | CONTEXT_DATA{ 281 | 40 282 | 100.0 283 | 10 284 | 6320.904102092164 285 | 20 286 | 2833.188934631764 287 | 30 288 | 0.0 289 | 41 290 | 350.0 291 | 140 292 | 350.0 293 | 145 294 | 100.0 295 | 174 296 | 1 297 | 175 298 | 1 299 | 176 300 | 0 301 | 177 302 | 0 303 | 290 304 | 1 305 | 304 306 | I am leader too 307 | 11 308 | 0.0 309 | 21 310 | 0.0 311 | 31 312 | 1.0 313 | 340 314 | 60 315 | 12 316 | 6420.904102092164 317 | 22 318 | 3010.988934631764 319 | 32 320 | 0.0 321 | 13 322 | 1.0 323 | 23 324 | 0.0 325 | 33 326 | 0.0 327 | 42 328 | 0.0 329 | 43 330 | 0.0 331 | 44 332 | 0.0 333 | 45 334 | 1.0 335 | 170 336 | 1 337 | 90 338 | -939524096 339 | 171 340 | 1 341 | 172 342 | 1 343 | 91 344 | -939524096 345 | 141 346 | 1.5 347 | 92 348 | 0 349 | 291 350 | 0 351 | 292 352 | 0 353 | 173 354 | 0 355 | 293 356 | 0 357 | 142 358 | 0.0 359 | 143 360 | 0.0 361 | 294 362 | 0 363 | 295 364 | 0 365 | 296 366 | 0 367 | 110 368 | 0.0 369 | 120 370 | 0.0 371 | 130 372 | 0.0 373 | 111 374 | 1.0 375 | 121 376 | 0.0 377 | 131 378 | 0.0 379 | 112 380 | 0.0 381 | 122 382 | 1.0 383 | 132 384 | 0.0 385 | 297 386 | 0 387 | 302 388 | LEADER{ 389 | 290 390 | 1 391 | 291 392 | 1 393 | 10 394 | 6320.904102092164 395 | 20 396 | 2833.188934631764 397 | 30 398 | 0.0 399 | 11 400 | 1.0 401 | 21 402 | 0.0 403 | 31 404 | 0.0 405 | 90 406 | 0 407 | 40 408 | 0.0 409 | 304 410 | LEADER_LINE{ 411 | 10 412 | 2328.832202913205 413 | 20 414 | 749.092575501571 415 | 30 416 | 0.0 417 | 10 418 | 3282.819972937589 419 | 20 420 | 3244.137512488422 421 | 30 422 | 0.0 423 | 10 424 | 4398.251827119944 425 | 20 426 | 2114.028923382613 427 | 30 428 | 0.0 429 | 10 430 | 4809.200404976602 431 | 20 432 | 3567.025680804367 433 | 30 434 | 0.0 435 | 10 436 | 5792.541644847891 437 | 20 438 | 2833.188934631764 439 | 30 440 | 0.0 441 | 91 442 | 0 443 | 305 444 | } 445 | 303 446 | } 447 | 301 448 | } 449 | 340 450 | 61 451 | 90 452 | 50657520 453 | 170 454 | 1 455 | 91 456 | -1056964608 457 | 341 458 | 14 459 | 171 460 | -2 461 | 290 462 | 0 463 | 291 464 | 0 465 | 41 466 | 0.0 467 | 42 468 | 350.0 469 | 172 470 | 2 471 | 343 472 | 60 473 | 173 474 | 1 475 | 95 476 | 1 477 | 174 478 | 2 479 | 175 480 | 0 481 | 92 482 | -939524096 483 | 292 484 | 0 485 | 93 486 | -1056964608 487 | 10 488 | 1.0 489 | 20 490 | 1.0 491 | 30 492 | 1.0 493 | 43 494 | 0.0 495 | 176 496 | 0 497 | 293 498 | 0 499 | 294 500 | 0 501 | 178 502 | 0 503 | 179 504 | 1 505 | 45 506 | 100.0 507 | 1001 508 | ACAD_MLEADERVER 509 | 1070 510 | 2 511 | 0 512 | MULTILEADER 513 | 5 514 | 64 515 | 330 516 | 1F 517 | 100 518 | AcDbEntity 519 | 8 520 | Default 521 | 92 522 | 512 523 | 310 524 | 000200000B0000000C00000013000000993A00000C0000000E00000001010000D80000002600000081BEADEEC70EA7C02612A38485E2A740000000000000000000000000000000000000000000000000000000000000F03F000000000000F03F000000000000000000000000000000004900200061006D0020006C00650061 525 | 310 526 | 0064006500720000000B000000010000000000000000E07540000000000000F03F0000000000000000000000000000F03F00000000000000000000000000000000000000000000000000000000010000000000000041007200690061006C00000061007200690061006C002E007400740066000000000000000C0000001300 527 | 310 528 | 0000112700000C00000013000000010000000C0000000E000000120000000C00000016000000000000C20C000000140000000100000054000000070000000300000067AC660AA87B9640C234D285A4AC91400000000000000000AC7C038953169740DE41398091538840000000000000000026B8B7F370BA9440A1C6808237 529 | 310 530 | 2E914000000000000000000C00000013000000891300006C000000200000000300000046320F7F0C9B9540B27D29046E6D91400000000000000000226D0C46339E88408C7809EBEB3AA9400000000000000000785AD4DBA51079C08C7809EBEB3AA94000000000000000000000000000000000000000000000000000000000 531 | 310 532 | 0000F03F 533 | 100 534 | AcDbMLeader 535 | 300 536 | CONTEXT_DATA{ 537 | 40 538 | 100.0 539 | 10 540 | -3005.890492848878 541 | 20 542 | 3229.460777564969 543 | 30 544 | 0.0 545 | 41 546 | 350.0 547 | 140 548 | 350.0 549 | 145 550 | 100.0 551 | 174 552 | 1 553 | 175 554 | 1 555 | 176 556 | 0 557 | 177 558 | 0 559 | 290 560 | 1 561 | 304 562 | I am leader 563 | 11 564 | 0.0 565 | 21 566 | 0.0 567 | 31 568 | 1.0 569 | 340 570 | 60 571 | 12 572 | -2905.890492848878 573 | 22 574 | 3407.260777564969 575 | 32 576 | 0.0 577 | 13 578 | 1.0 579 | 23 580 | 0.0 581 | 33 582 | 0.0 583 | 42 584 | 0.0 585 | 43 586 | 0.0 587 | 44 588 | 0.0 589 | 45 590 | 1.0 591 | 170 592 | 1 593 | 90 594 | -939524096 595 | 171 596 | 1 597 | 172 598 | 1 599 | 91 600 | -939524096 601 | 141 602 | 1.5 603 | 92 604 | 0 605 | 291 606 | 0 607 | 292 608 | 0 609 | 173 610 | 0 611 | 293 612 | 0 613 | 142 614 | 0.0 615 | 143 616 | 0.0 617 | 294 618 | 0 619 | 295 620 | 0 621 | 296 622 | 0 623 | 110 624 | 0.0 625 | 120 626 | 0.0 627 | 130 628 | 0.0 629 | 111 630 | 1.0 631 | 121 632 | 0.0 633 | 131 634 | 0.0 635 | 112 636 | 0.0 637 | 122 638 | 1.0 639 | 132 640 | 0.0 641 | 297 642 | 0 643 | 302 644 | LEADER{ 645 | 290 646 | 1 647 | 291 648 | 1 649 | 10 650 | -401.0404928488783 651 | 20 652 | 3229.460777564969 653 | 30 654 | 0.0 655 | 11 656 | -1.0 657 | 21 658 | 0.0 659 | 31 660 | 0.0 661 | 90 662 | 0 663 | 40 664 | 0.0 665 | 304 666 | LEADER_LINE{ 667 | 10 668 | 1477.581577352986 669 | 20 670 | 778.4460453484751 671 | 30 672 | 0.0 673 | 10 674 | 787.7750359507374 675 | 20 676 | 3229.460777564969 677 | 30 678 | 0.0 679 | 91 680 | 0 681 | 305 682 | } 683 | 303 684 | } 685 | 301 686 | } 687 | 340 688 | 61 689 | 90 690 | 50657520 691 | 170 692 | 1 693 | 91 694 | -1056964608 695 | 341 696 | 14 697 | 171 698 | -2 699 | 290 700 | 0 701 | 291 702 | 0 703 | 41 704 | 0.0 705 | 42 706 | 350.0 707 | 172 708 | 2 709 | 343 710 | 60 711 | 173 712 | 1 713 | 95 714 | 1 715 | 174 716 | 2 717 | 175 718 | 0 719 | 92 720 | -939524096 721 | 292 722 | 0 723 | 93 724 | -1056964608 725 | 10 726 | 1.0 727 | 20 728 | 1.0 729 | 30 730 | 1.0 731 | 43 732 | 0.0 733 | 176 734 | 0 735 | 293 736 | 0 737 | 294 738 | 0 739 | 178 740 | 0 741 | 179 742 | 1 743 | 45 744 | 100.0 745 | 1001 746 | ACAD_MLEADERVER 747 | 1070 748 | 2 749 | 0 750 | ENDSEC 751 | 0 752 | EOF 753 | -------------------------------------------------------------------------------- /test/data/mtext-test.approved.txt: -------------------------------------------------------------------------------- 1 | { 2 | "blocks": { 3 | "*Model_Space": { 4 | "handle": "20", 5 | "layer": "0", 6 | "name": "*Model_Space", 7 | "name2": "*Model_Space", 8 | "ownerHandle": "1F", 9 | "position": { 10 | "x": 0, 11 | "y": 0, 12 | "z": 0 13 | }, 14 | "xrefPath": "" 15 | }, 16 | "*Paper_Space": { 17 | "handle": "5A", 18 | "layer": "0", 19 | "name": "*Paper_Space", 20 | "name2": "*Paper_Space", 21 | "ownerHandle": "58", 22 | "paperSpace": true, 23 | "position": { 24 | "x": 0, 25 | "y": 0, 26 | "z": 0 27 | }, 28 | "xrefPath": "" 29 | }, 30 | "*Paper_Space0": { 31 | "handle": "5F", 32 | "layer": "0", 33 | "name": "*Paper_Space0", 34 | "name2": "*Paper_Space0", 35 | "ownerHandle": "5D", 36 | "paperSpace": true, 37 | "position": { 38 | "x": 0, 39 | "y": 0, 40 | "z": 0 41 | }, 42 | "xrefPath": "" 43 | } 44 | }, 45 | "entities": [ 46 | { 47 | "attachmentPoint": 1, 48 | "drawingDirection": 5, 49 | "extendedData": { 50 | "applicationName": "ACAD", 51 | "customStrings": [ 52 | "ACAD_MTEXT_COLUMN_INFO_BEGIN", 53 | "ACAD_MTEXT_COLUMN_INFO_END" 54 | ] 55 | }, 56 | "handle": "26B", 57 | "height": 0.2, 58 | "layer": "0", 59 | "ownerHandle": "1F", 60 | "position": { 61 | "x": 0.3180789370493358, 62 | "y": 5.389340577865198, 63 | "z": 0 64 | }, 65 | "text": "Lorem ipsum dolor sit amet consectetur adipiscing elit vitae, congue mus odio lobortis habitasse parturient sem. Rutrum volutpat sagittis fringilla sollicitudin cum nisl suspendisse non, mi habitant habitasse nunc pellentesque vitae maecenas, cursuslectus nascetur nulla parturient leo luctus. Interdum sapien augue ullamcorper dis ultrices mollis leo netus ante, platea quam at eros urna natoque habitasse nulla fringilla curabitur, egestas facilisis iaculis euismod tempor aliquet curae molestie.Dapibus bibendum scelerisque tempus netus mus hac euismod vestibulum proin tristique non, congue ultrices cras lobortis nam lacus magnis iaculis at donec justo maecenas, est convallis inceptos vel nisi eu natoque ante nisl sapien. Facilisi per dui lobortis eleifend facilisis quam luctus, nunc semper neque cubilia cursus fringilla, nisl vehicula viverra diam auctor vitae. Est enim gravida nibh non pretium aptent nulla egestas praesent, varius malesuada felis commodo leo id lacinia montes, magna turpis sagittis imperdie.", 66 | "type": "MTEXT", 67 | "width": 8.98565600810167 68 | }, 69 | { 70 | "attachmentPoint": 2, 71 | "drawingDirection": 5, 72 | "handle": "272", 73 | "height": 0.2, 74 | "layer": "0", 75 | "ownerHandle": "1F", 76 | "position": { 77 | "x": 16.6297525520321, 78 | "y": 5.552640932220924, 79 | "z": 0 80 | }, 81 | "text": "Lorem ipsum dolor sit amet consectetur adipiscing elit vitae, congue mus odio lobortis habitasse parturient sem.", 82 | "type": "MTEXT", 83 | "width": 8.98565600810167 84 | } 85 | ], 86 | "header": { 87 | "$3DDWFPREC": 2, 88 | "$ACADMAINTVER": 125, 89 | "$ACADVER": "AC1027", 90 | "$ANGBASE": 0, 91 | "$ANGDIR": 0, 92 | "$ATTMODE": 1, 93 | "$AUNITS": 0, 94 | "$AUPREC": 0, 95 | "$CAMERADISPLAY": false, 96 | "$CAMERAHEIGHT": 0, 97 | "$CECOLOR": 256, 98 | "$CELTSCALE": 1, 99 | "$CELTYPE": "ByLayer", 100 | "$CELWEIGHT": -1, 101 | "$CEPSNTYPE": 0, 102 | "$CHAMFERA": 0, 103 | "$CHAMFERB": 0, 104 | "$CHAMFERC": 0, 105 | "$CHAMFERD": 0, 106 | "$CLAYER": "0", 107 | "$CMATERIAL": "96", 108 | "$CMLJUST": 0, 109 | "$CMLSCALE": 1, 110 | "$CMLSTYLE": "Standard", 111 | "$CSHADOW": 0, 112 | "$DGNFRAME": 0, 113 | "$DIMADEC": 0, 114 | "$DIMALT": 0, 115 | "$DIMALTD": 2, 116 | "$DIMALTF": 25.4, 117 | "$DIMALTRND": 0, 118 | "$DIMALTTD": 2, 119 | "$DIMALTTZ": 0, 120 | "$DIMALTU": 2, 121 | "$DIMALTZ": 0, 122 | "$DIMAPOST": "", 123 | "$DIMARCSYM": 0, 124 | "$DIMASO": 1, 125 | "$DIMASSOC": 2, 126 | "$DIMASZ": 0.18, 127 | "$DIMATFIT": 3, 128 | "$DIMAUNIT": 0, 129 | "$DIMAZIN": 0, 130 | "$DIMBLK": "", 131 | "$DIMBLK1": "", 132 | "$DIMBLK2": "", 133 | "$DIMCEN": 0.09, 134 | "$DIMCLRD": 0, 135 | "$DIMCLRE": 0, 136 | "$DIMCLRT": 0, 137 | "$DIMDEC": 4, 138 | "$DIMDLE": 0, 139 | "$DIMDLI": 0.38, 140 | "$DIMDSEP": 46, 141 | "$DIMEXE": 0.18, 142 | "$DIMEXO": 0.0625, 143 | "$DIMFRAC": 0, 144 | "$DIMFXL": 1, 145 | "$DIMFXLON": 0, 146 | "$DIMGAP": 0.09, 147 | "$DIMJOGANG": 0.7853981633974483, 148 | "$DIMJUST": 0, 149 | "$DIMLDRBLK": "", 150 | "$DIMLFAC": 1, 151 | "$DIMLIM": 0, 152 | "$DIMLTEX1": "", 153 | "$DIMLTEX2": "", 154 | "$DIMLTYPE": "", 155 | "$DIMLUNIT": 2, 156 | "$DIMLWD": -2, 157 | "$DIMLWE": -2, 158 | "$DIMPOST": "", 159 | "$DIMRND": 0, 160 | "$DIMSAH": 0, 161 | "$DIMSCALE": 1, 162 | "$DIMSD1": 0, 163 | "$DIMSD2": 0, 164 | "$DIMSE1": 0, 165 | "$DIMSE2": 0, 166 | "$DIMSHO": 1, 167 | "$DIMSOXD": 0, 168 | "$DIMSTYLE": "Standard", 169 | "$DIMTAD": 0, 170 | "$DIMTDEC": 4, 171 | "$DIMTFAC": 1, 172 | "$DIMTFILL": 0, 173 | "$DIMTFILLCLR": 0, 174 | "$DIMTIH": 1, 175 | "$DIMTIX": 0, 176 | "$DIMTM": 0, 177 | "$DIMTMOVE": 0, 178 | "$DIMTOFL": 0, 179 | "$DIMTOH": 1, 180 | "$DIMTOL": 0, 181 | "$DIMTOLJ": 1, 182 | "$DIMTP": 0, 183 | "$DIMTSZ": 0, 184 | "$DIMTVP": 0, 185 | "$DIMTXSTY": "Standard", 186 | "$DIMTXT": 0.18, 187 | "$DIMTXTDIRECTION": 0, 188 | "$DIMTZIN": 0, 189 | "$DIMUPT": 0, 190 | "$DIMZIN": 0, 191 | "$DISPSILH": 0, 192 | "$DWFFRAME": 2, 193 | "$DWGCODEPAGE": "ANSI_1252", 194 | "$ELEVATION": 0, 195 | "$ENDCAPS": 0, 196 | "$EXTMAX": { 197 | "x": 35.77780313523698, 198 | "y": 23.59224206458088, 199 | "z": 0 200 | }, 201 | "$EXTMIN": { 202 | "x": 0.2965236846618869, 203 | "y": 0.443001332753784, 204 | "z": 0 205 | }, 206 | "$EXTNAMES": true, 207 | "$FILLETRAD": 0, 208 | "$FILLMODE": 1, 209 | "$FINGERPRINTGUID": "{FDAE80E6-93AC-8B41-9270-67E6B58D8DBE}", 210 | "$HALOGAP": 0, 211 | "$HANDSEED": "289", 212 | "$HIDETEXT": 1, 213 | "$HYPERLINKBASE": "", 214 | "$INDEXCTL": 0, 215 | "$INSBASE": { 216 | "x": 0, 217 | "y": 0, 218 | "z": 0 219 | }, 220 | "$INSUNITS": 1, 221 | "$INTERFERECOLOR": 1, 222 | "$INTERFEREOBJVS": "A3", 223 | "$INTERFEREVPVS": "A0", 224 | "$INTERSECTIONCOLOR": 257, 225 | "$INTERSECTIONDISPLAY": 0, 226 | "$JOINSTYLE": 0, 227 | "$LASTSAVEDBY": "bzuil", 228 | "$LATITUDE": 37.795, 229 | "$LENSLENGTH": 50, 230 | "$LIGHTGLYPHDISPLAY": 1, 231 | "$LIMCHECK": 0, 232 | "$LIMMAX": { 233 | "x": 12, 234 | "y": 9 235 | }, 236 | "$LIMMIN": { 237 | "x": 0, 238 | "y": 0 239 | }, 240 | "$LOFTANG1": 1.570796326794896, 241 | "$LOFTANG2": 1.570796326794896, 242 | "$LOFTMAG1": 0, 243 | "$LOFTMAG2": 0, 244 | "$LOFTNORMALS": 1, 245 | "$LOFTPARAM": 7, 246 | "$LONGITUDE": -122.394, 247 | "$LTSCALE": 1, 248 | "$LUNITS": 2, 249 | "$LUPREC": 4, 250 | "$LWDISPLAY": false, 251 | "$MAXACTVP": 64, 252 | "$MEASUREMENT": 0, 253 | "$MENU": ".", 254 | "$MIRRTEXT": 0, 255 | "$NORTHDIRECTION": 0, 256 | "$OBSCOLOR": 257, 257 | "$OBSLTYPE": 0, 258 | "$OLESTARTUP": false, 259 | "$ORTHOMODE": 0, 260 | "$PDMODE": 0, 261 | "$PDSIZE": 0, 262 | "$PELEVATION": 0, 263 | "$PEXTMAX": { 264 | "x": 0, 265 | "y": 0, 266 | "z": 0 267 | }, 268 | "$PEXTMIN": { 269 | "x": 0, 270 | "y": 0, 271 | "z": 0 272 | }, 273 | "$PINSBASE": { 274 | "x": 0, 275 | "y": 0, 276 | "z": 0 277 | }, 278 | "$PLIMCHECK": 0, 279 | "$PLIMMAX": { 280 | "x": 12, 281 | "y": 9 282 | }, 283 | "$PLIMMIN": { 284 | "x": 0, 285 | "y": 0 286 | }, 287 | "$PLINEGEN": 0, 288 | "$PLINEWID": 0, 289 | "$PROJECTNAME": "", 290 | "$PROXYGRAPHICS": 1, 291 | "$PSLTSCALE": 1, 292 | "$PSOLHEIGHT": 4, 293 | "$PSOLWIDTH": 0.25, 294 | "$PSTYLEMODE": true, 295 | "$PSVPSCALE": 0, 296 | "$PUCSBASE": "", 297 | "$PUCSNAME": "", 298 | "$PUCSORG": { 299 | "x": 0, 300 | "y": 0, 301 | "z": 0 302 | }, 303 | "$PUCSORGBACK": { 304 | "x": 0, 305 | "y": 0, 306 | "z": 0 307 | }, 308 | "$PUCSORGBOTTOM": { 309 | "x": 0, 310 | "y": 0, 311 | "z": 0 312 | }, 313 | "$PUCSORGFRONT": { 314 | "x": 0, 315 | "y": 0, 316 | "z": 0 317 | }, 318 | "$PUCSORGLEFT": { 319 | "x": 0, 320 | "y": 0, 321 | "z": 0 322 | }, 323 | "$PUCSORGRIGHT": { 324 | "x": 0, 325 | "y": 0, 326 | "z": 0 327 | }, 328 | "$PUCSORGTOP": { 329 | "x": 0, 330 | "y": 0, 331 | "z": 0 332 | }, 333 | "$PUCSORTHOREF": "", 334 | "$PUCSORTHOVIEW": 0, 335 | "$PUCSXDIR": { 336 | "x": 1, 337 | "y": 0, 338 | "z": 0 339 | }, 340 | "$PUCSYDIR": { 341 | "x": 0, 342 | "y": 1, 343 | "z": 0 344 | }, 345 | "$QTEXTMODE": 0, 346 | "$REALWORLDSCALE": true, 347 | "$REGENMODE": 1, 348 | "$REQUIREDVERSIONS": 0, 349 | "$SHADEDGE": 3, 350 | "$SHADEDIF": 70, 351 | "$SHADOWPLANELOCATION": 0, 352 | "$SHOWHIST": 1, 353 | "$SKETCHINC": 0.1, 354 | "$SKPOLY": 0, 355 | "$SOLIDHIST": 0, 356 | "$SORTENTS": 127, 357 | "$SPLFRAME": 0, 358 | "$SPLINESEGS": 8, 359 | "$SPLINETYPE": 6, 360 | "$STEPSIZE": 6, 361 | "$STEPSPERSEC": 2, 362 | "$STYLESHEET": "", 363 | "$SURFTAB1": 6, 364 | "$SURFTAB2": 6, 365 | "$SURFTYPE": 6, 366 | "$SURFU": 6, 367 | "$SURFV": 6, 368 | "$TDCREATE": 2458528.811944445, 369 | "$TDINDWG": 0.0113888889, 370 | "$TDUCREATE": 2458529.145277778, 371 | "$TDUPDATE": 2458528.989722222, 372 | "$TDUSRTIMER": 0.0113888889, 373 | "$TDUUPDATE": 2458529.323055556, 374 | "$TEXTSIZE": 0.2, 375 | "$TEXTSTYLE": "Standard", 376 | "$THICKNESS": 0, 377 | "$TILEMODE": 1, 378 | "$TILEMODELIGHTSYNCH": 1, 379 | "$TIMEZONE": -8000, 380 | "$TRACEWID": 0.05, 381 | "$TREEDEPTH": 3020, 382 | "$UCSBASE": "", 383 | "$UCSNAME": "", 384 | "$UCSORG": { 385 | "x": 0, 386 | "y": 0, 387 | "z": 0 388 | }, 389 | "$UCSORGBACK": { 390 | "x": 0, 391 | "y": 0, 392 | "z": 0 393 | }, 394 | "$UCSORGBOTTOM": { 395 | "x": 0, 396 | "y": 0, 397 | "z": 0 398 | }, 399 | "$UCSORGFRONT": { 400 | "x": 0, 401 | "y": 0, 402 | "z": 0 403 | }, 404 | "$UCSORGLEFT": { 405 | "x": 0, 406 | "y": 0, 407 | "z": 0 408 | }, 409 | "$UCSORGRIGHT": { 410 | "x": 0, 411 | "y": 0, 412 | "z": 0 413 | }, 414 | "$UCSORGTOP": { 415 | "x": 0, 416 | "y": 0, 417 | "z": 0 418 | }, 419 | "$UCSORTHOREF": "", 420 | "$UCSORTHOVIEW": 0, 421 | "$UCSXDIR": { 422 | "x": 1, 423 | "y": 0, 424 | "z": 0 425 | }, 426 | "$UCSYDIR": { 427 | "x": 0, 428 | "y": 1, 429 | "z": 0 430 | }, 431 | "$UNITMODE": 0, 432 | "$USERI1": 0, 433 | "$USERI2": 0, 434 | "$USERI3": 0, 435 | "$USERI4": 0, 436 | "$USERI5": 0, 437 | "$USERR1": 0, 438 | "$USERR2": 0, 439 | "$USERR3": 0, 440 | "$USERR4": 0, 441 | "$USERR5": 0, 442 | "$USRTIMER": 1, 443 | "$VERSIONGUID": "{8C84135B-E9E2-8A4F-B585-309CF8EF7F09}", 444 | "$VISRETAIN": 1, 445 | "$WORLDVIEW": 1, 446 | "$XCLIPFRAME": 2, 447 | "$XEDIT": true 448 | }, 449 | "tables": { 450 | "layer": { 451 | "handle": "2", 452 | "layers": { 453 | "0": { 454 | "color": 16777215, 455 | "colorIndex": 7, 456 | "frozen": false, 457 | "name": "0", 458 | "visible": true 459 | } 460 | }, 461 | "ownerHandle": "0" 462 | }, 463 | "lineType": { 464 | "handle": "5", 465 | "lineTypes": { 466 | "ByBlock": { 467 | "description": "", 468 | "name": "ByBlock", 469 | "patternLength": 0 470 | }, 471 | "ByLayer": { 472 | "description": "", 473 | "name": "ByLayer", 474 | "patternLength": 0 475 | }, 476 | "Continuous": { 477 | "description": "Solid line", 478 | "name": "Continuous", 479 | "patternLength": 0 480 | } 481 | }, 482 | "ownerHandle": "0" 483 | }, 484 | "viewPort": { 485 | "handle": "8", 486 | "ownerHandle": "0", 487 | "viewPorts": [ 488 | { 489 | "ambientColor": 3355443, 490 | "backClippingPlane": 0, 491 | "center": { 492 | "x": 13.93835439371528, 493 | "y": 3.720281475640653 494 | }, 495 | "defaultLightingOn": true, 496 | "frontClippingPlane": 0, 497 | "gridSpacing": { 498 | "x": 0.5, 499 | "y": 0.5 500 | }, 501 | "lensLength": 50, 502 | "lowerLeftCorner": { 503 | "x": 0, 504 | "y": 0 505 | }, 506 | "name": "*Active", 507 | "orthographicType": 0, 508 | "ownerHandle": "8", 509 | "renderMode": 0, 510 | "snapBasePoint": { 511 | "x": 0, 512 | "y": 0 513 | }, 514 | "snapRotationAngle": 0, 515 | "snapSpacing": { 516 | "x": 0.5, 517 | "y": 0.5 518 | }, 519 | "ucsOrigin": { 520 | "x": 0, 521 | "y": 0, 522 | "z": 0 523 | }, 524 | "ucsXAxis": { 525 | "x": 1, 526 | "y": 0, 527 | "z": 0 528 | }, 529 | "ucsYAxis": { 530 | "x": 0, 531 | "y": 1, 532 | "z": 0 533 | }, 534 | "upperRightCorner": { 535 | "x": 1, 536 | "y": 1 537 | }, 538 | "viewDirectionFromTarget": { 539 | "x": 0, 540 | "y": 0, 541 | "z": 1 542 | }, 543 | "viewTarget": { 544 | "x": 0, 545 | "y": 0, 546 | "z": 0 547 | }, 548 | "viewTwistAngle": 0 549 | } 550 | ] 551 | } 552 | } 553 | } 554 | -------------------------------------------------------------------------------- /test/data/splines.dxf: -------------------------------------------------------------------------------- 1 | 0 2 | SECTION 3 | 2 4 | HEADER 5 | 0 6 | ENDSEC 7 | 0 8 | SECTION 9 | 2 10 | ENTITIES 11 | 0 12 | SPLINE 13 | 5 14 | 3D 15 | 330 16 | 157 17 | 100 18 | AcDbEntity 19 | 8 20 | PLOTLINES 21 | 100 22 | AcDbSpline 23 | 210 24 | 0.0 25 | 220 26 | 0.0 27 | 230 28 | 1.0 29 | 70 30 | 1064 31 | 71 32 | 3 33 | 72 34 | 9 35 | 73 36 | 5 37 | 74 38 | 3 39 | 42 40 | 0.000000001 41 | 43 42 | 0.0000000001 43 | 44 44 | 0.0 45 | 12 46 | 0.9514183274466854 47 | 22 48 | 0.3079012279913022 49 | 32 50 | 0.0 51 | 40 52 | 0.0 53 | 40 54 | 0.0 55 | 40 56 | 0.0 57 | 40 58 | 0.0 59 | 40 60 | 1547.322808138777 61 | 40 62 | 5019.938770381674 63 | 40 64 | 5019.938770381674 65 | 40 66 | 5019.938770381674 67 | 40 68 | 5019.938770381674 69 | 10 70 | 0.0 71 | 20 72 | 0.0 73 | 30 74 | 0.0 75 | 10 76 | 490.717092713168 77 | 20 78 | 158.8075309082932 79 | 30 80 | 0.0 81 | 10 82 | 2164.905820751131 83 | 20 84 | 388.1223313710202 85 | 30 86 | 0.0 87 | 10 88 | 3837.689038507039 89 | 20 90 | 353.4902462273104 91 | 30 92 | 0.0 93 | 10 94 | 4994.861260930288 95 | 20 96 | 329.5329955163307 97 | 30 98 | 0.0 99 | 11 100 | 0.0 101 | 21 102 | 0.0 103 | 31 104 | 0.0 105 | 11 106 | 1522.67200320285 107 | 21 108 | 275.0960618560202 109 | 31 110 | 0.0 111 | 11 112 | 4994.861260930288 113 | 21 114 | 329.5329955163307 115 | 31 116 | 0.0 117 | 0 118 | SPLINE 119 | 5 120 | 3E 121 | 330 122 | 157 123 | 100 124 | AcDbEntity 125 | 8 126 | PLOTLINES 127 | 100 128 | AcDbSpline 129 | 210 130 | 0.0 131 | 220 132 | 0.0 133 | 230 134 | 1.0 135 | 70 136 | 8 137 | 71 138 | 3 139 | 72 140 | 26 141 | 73 142 | 22 143 | 74 144 | 0 145 | 42 146 | 0.000000001 147 | 43 148 | 0.001 149 | 40 150 | 0.0 151 | 40 152 | 0.0 153 | 40 154 | 0.0 155 | 40 156 | 0.0 157 | 40 158 | 294.0525150032295 159 | 40 160 | 294.0525150032295 161 | 40 162 | 1045.910856597887 163 | 40 164 | 1045.910856597887 165 | 40 166 | 1224.445418796694 167 | 40 168 | 1224.445418796694 169 | 40 170 | 1454.016505907184 171 | 40 172 | 1454.016505907184 173 | 40 174 | 1572.806679130005 175 | 40 176 | 1572.806679130005 177 | 40 178 | 1691.596852352826 179 | 40 180 | 1691.596852352826 181 | 40 182 | 1929.177198798468 183 | 40 184 | 1929.177198798468 185 | 40 186 | 2404.337891689753 187 | 40 188 | 2404.337891689753 189 | 40 190 | 3354.659277472323 191 | 40 192 | 3354.659277472323 193 | 40 194 | 5015.653135237717 195 | 40 196 | 5015.653135237717 197 | 40 198 | 5015.653135237717 199 | 40 200 | 5015.653135237717 201 | 10 202 | -3.910345595490071 203 | 20 204 | 12.08301275857048 205 | 30 206 | 0.0 207 | 10 208 | 89.61730010503788 209 | 20 210 | 42.35074686835108 211 | 30 212 | 0.0 213 | 10 214 | 184.0439740094698 215 | 20 216 | 69.42067550989128 217 | 30 218 | 0.0 219 | 10 220 | 522.4770607652581 221 | 20 222 | 155.8817672278711 223 | 30 224 | 0.0 225 | 10 226 | 770.4801029905291 227 | 20 228 | 199.9804308248713 229 | 30 230 | 0.0 231 | 10 232 | 1079.587521541959 233 | 20 234 | 241.21623757007 235 | 30 236 | 0.0 237 | 10 238 | 1139.003629790081 239 | 20 240 | 248.5213454592013 241 | 30 242 | 0.0 243 | 10 244 | 1274.962277830939 245 | 20 246 | 264.0530430007511 247 | 30 248 | 0.0 249 | 10 250 | 1351.545278854538 251 | 20 252 | 271.9460988128703 253 | 30 254 | 0.0 255 | 10 256 | 1467.784975350118 257 | 20 258 | 282.9561993903517 259 | 30 260 | 0.0 261 | 10 262 | 1507.426369672711 263 | 20 264 | 286.5407381210116 265 | 30 266 | 0.0 267 | 10 268 | 1586.7020874704 269 | 20 270 | 293.4221664132911 271 | 30 272 | 0.0 273 | 10 274 | 1626.33866183868 275 | 20 276 | 296.7160046281916 277 | 30 278 | 0.0 279 | 10 280 | 1745.24459612016 281 | 20 282 | 306.1720917982002 283 | 30 284 | 0.0 285 | 10 286 | 1824.510166696128 287 | 20 288 | 311.90891354419 289 | 30 290 | 0.0 291 | 10 292 | 2062.292259321239 293 | 20 294 | 327.5392634975415 295 | 30 296 | 0.0 297 | 10 298 | 2220.79415577079 299 | 20 300 | 335.8526816976901 301 | 30 302 | 0.0 303 | 10 304 | 2696.245919829701 305 | 20 306 | 355.4450722011516 307 | 30 308 | 0.0 309 | 10 310 | 3013.141808632271 311 | 20 312 | 361.3762829349107 313 | 30 314 | 0.0 315 | 10 316 | 3883.754181435569 317 | 20 318 | 365.2047369340217 319 | 30 320 | 0.0 321 | 10 322 | 4437.349959065938 323 | 20 324 | 353.7779394056507 325 | 30 326 | 0.0 327 | 10 328 | 4990.839855556188 329 | 20 330 | 342.3189730325903 331 | 30 332 | 0.0 333 | 0 334 | ENDSEC 335 | 0 336 | EOF 337 | -------------------------------------------------------------------------------- /test/data/splines.expected.json: -------------------------------------------------------------------------------- 1 | { 2 | "header": {}, 3 | "entities": [ 4 | { 5 | "type": "SPLINE", 6 | "handle": "3D", 7 | "ownerHandle": "157", 8 | "layer": "PLOTLINES", 9 | "normalVector": { 10 | "x": 0, 11 | "y": 0, 12 | "z": 1 13 | }, 14 | "planar": true, 15 | "degreeOfSplineCurve": 3, 16 | "numberOfKnots": 9, 17 | "numberOfControlPoints": 5, 18 | "numberOfFitPoints": 3, 19 | "startTangent": { 20 | "x": 0.9514183274466854, 21 | "y": 0.3079012279913022, 22 | "z": 0 23 | }, 24 | "knotValues": [ 25 | 0, 26 | 0, 27 | 0, 28 | 0, 29 | 1547.322808138777, 30 | 5019.938770381674, 31 | 5019.938770381674, 32 | 5019.938770381674, 33 | 5019.938770381674 34 | ], 35 | "controlPoints": [ 36 | { 37 | "x": 0, 38 | "y": 0, 39 | "z": 0 40 | }, 41 | { 42 | "x": 490.717092713168, 43 | "y": 158.8075309082932, 44 | "z": 0 45 | }, 46 | { 47 | "x": 2164.905820751131, 48 | "y": 388.1223313710202, 49 | "z": 0 50 | }, 51 | { 52 | "x": 3837.689038507039, 53 | "y": 353.4902462273104, 54 | "z": 0 55 | }, 56 | { 57 | "x": 4994.861260930288, 58 | "y": 329.5329955163307, 59 | "z": 0 60 | } 61 | ], 62 | "fitPoints": [ 63 | { 64 | "x": 0, 65 | "y": 0, 66 | "z": 0 67 | }, 68 | { 69 | "x": 1522.67200320285, 70 | "y": 275.0960618560202, 71 | "z": 0 72 | }, 73 | { 74 | "x": 4994.861260930288, 75 | "y": 329.5329955163307, 76 | "z": 0 77 | } 78 | ] 79 | }, 80 | { 81 | "type": "SPLINE", 82 | "handle": "3E", 83 | "ownerHandle": "157", 84 | "layer": "PLOTLINES", 85 | "normalVector": { 86 | "x": 0, 87 | "y": 0, 88 | "z": 1 89 | }, 90 | "planar": true, 91 | "degreeOfSplineCurve": 3, 92 | "numberOfKnots": 26, 93 | "numberOfControlPoints": 22, 94 | "numberOfFitPoints": 0, 95 | "knotValues": [ 96 | 0, 97 | 0, 98 | 0, 99 | 0, 100 | 294.0525150032295, 101 | 294.0525150032295, 102 | 1045.910856597887, 103 | 1045.910856597887, 104 | 1224.445418796694, 105 | 1224.445418796694, 106 | 1454.016505907184, 107 | 1454.016505907184, 108 | 1572.806679130005, 109 | 1572.806679130005, 110 | 1691.596852352826, 111 | 1691.596852352826, 112 | 1929.177198798468, 113 | 1929.177198798468, 114 | 2404.337891689753, 115 | 2404.337891689753, 116 | 3354.659277472323, 117 | 3354.659277472323, 118 | 5015.653135237717, 119 | 5015.653135237717, 120 | 5015.653135237717, 121 | 5015.653135237717 122 | ], 123 | "controlPoints": [ 124 | { 125 | "x": -3.910345595490071, 126 | "y": 12.08301275857048, 127 | "z": 0 128 | }, 129 | { 130 | "x": 89.61730010503788, 131 | "y": 42.35074686835108, 132 | "z": 0 133 | }, 134 | { 135 | "x": 184.0439740094698, 136 | "y": 69.42067550989128, 137 | "z": 0 138 | }, 139 | { 140 | "x": 522.4770607652581, 141 | "y": 155.8817672278711, 142 | "z": 0 143 | }, 144 | { 145 | "x": 770.4801029905291, 146 | "y": 199.9804308248713, 147 | "z": 0 148 | }, 149 | { 150 | "x": 1079.587521541959, 151 | "y": 241.21623757007, 152 | "z": 0 153 | }, 154 | { 155 | "x": 1139.003629790081, 156 | "y": 248.5213454592013, 157 | "z": 0 158 | }, 159 | { 160 | "x": 1274.962277830939, 161 | "y": 264.0530430007511, 162 | "z": 0 163 | }, 164 | { 165 | "x": 1351.545278854538, 166 | "y": 271.9460988128703, 167 | "z": 0 168 | }, 169 | { 170 | "x": 1467.784975350118, 171 | "y": 282.9561993903517, 172 | "z": 0 173 | }, 174 | { 175 | "x": 1507.426369672711, 176 | "y": 286.5407381210116, 177 | "z": 0 178 | }, 179 | { 180 | "x": 1586.7020874704, 181 | "y": 293.4221664132911, 182 | "z": 0 183 | }, 184 | { 185 | "x": 1626.33866183868, 186 | "y": 296.7160046281916, 187 | "z": 0 188 | }, 189 | { 190 | "x": 1745.24459612016, 191 | "y": 306.1720917982002, 192 | "z": 0 193 | }, 194 | { 195 | "x": 1824.510166696128, 196 | "y": 311.90891354419, 197 | "z": 0 198 | }, 199 | { 200 | "x": 2062.292259321239, 201 | "y": 327.5392634975415, 202 | "z": 0 203 | }, 204 | { 205 | "x": 2220.79415577079, 206 | "y": 335.8526816976901, 207 | "z": 0 208 | }, 209 | { 210 | "x": 2696.245919829701, 211 | "y": 355.4450722011516, 212 | "z": 0 213 | }, 214 | { 215 | "x": 3013.141808632271, 216 | "y": 361.3762829349107, 217 | "z": 0 218 | }, 219 | { 220 | "x": 3883.754181435569, 221 | "y": 365.2047369340217, 222 | "z": 0 223 | }, 224 | { 225 | "x": 4437.349959065938, 226 | "y": 353.7779394056507, 227 | "z": 0 228 | }, 229 | { 230 | "x": 4990.839855556188, 231 | "y": 342.3189730325903, 232 | "z": 0 233 | } 234 | ] 235 | } 236 | ] 237 | } -------------------------------------------------------------------------------- /test/data/tables.dxf: -------------------------------------------------------------------------------- 1 | 0 2 | SECTION 3 | 2 4 | TABLES 5 | 0 6 | TABLE 7 | 2 8 | VPORT 9 | 5 10 | 8 11 | 330 12 | 0 13 | 100 14 | AcDbSymbolTable 15 | 70 16 | 1 17 | 0 18 | VPORT 19 | 5 20 | 94 21 | 330 22 | 8 23 | 100 24 | AcDbSymbolTableRecord 25 | 100 26 | AcDbViewportTableRecord 27 | 2 28 | *Active 29 | 70 30 | 0 31 | 10 32 | 0.0 33 | 20 34 | 0.0 35 | 11 36 | 1.0 37 | 21 38 | 1.0 39 | 12 40 | 23.34842155490301 41 | 22 42 | 8.680283835098334 43 | 13 44 | 0.0 45 | 23 46 | 0.0 47 | 14 48 | 0.5 49 | 24 50 | 0.5 51 | 15 52 | 0.5 53 | 25 54 | 0.5 55 | 16 56 | 0.0 57 | 26 58 | 0.0 59 | 36 60 | 1.0 61 | 17 62 | 0.0 63 | 27 64 | 0.0 65 | 37 66 | 0.0 67 | 40 68 | 37.36562314777483 69 | 41 70 | 2.152129817444218 71 | 42 72 | 50.0 73 | 43 74 | 0.0 75 | 44 76 | 0.0 77 | 50 78 | 0.0 79 | 51 80 | 0.0 81 | 71 82 | 0 83 | 72 84 | 1000 85 | 73 86 | 1 87 | 74 88 | 2 89 | 75 90 | 0 91 | 76 92 | 0 93 | 77 94 | 0 95 | 78 96 | 0 97 | 281 98 | 0 99 | 65 100 | 1 101 | 110 102 | 0.0 103 | 120 104 | 0.0 105 | 130 106 | 0.0 107 | 111 108 | 1.0 109 | 121 110 | 0.0 111 | 131 112 | 0.0 113 | 112 114 | 0.0 115 | 122 116 | 1.0 117 | 132 118 | 0.0 119 | 79 120 | 0 121 | 146 122 | 0.0 123 | 348 124 | 9F 125 | 60 126 | 3 127 | 61 128 | 5 129 | 292 130 | 1 131 | 282 132 | 1 133 | 141 134 | 0.0 135 | 142 136 | 0.0 137 | 63 138 | 250 139 | 421 140 | 3355443 141 | 1001 142 | ACAD_NAV_VCDISPLAY 143 | 1070 144 | 3 145 | 0 146 | ENDTAB 147 | 0 148 | TABLE 149 | 2 150 | LTYPE 151 | 5 152 | 5 153 | 330 154 | 0 155 | 100 156 | AcDbSymbolTable 157 | 70 158 | 10 159 | 0 160 | LTYPE 161 | 5 162 | 14 163 | 330 164 | 5 165 | 100 166 | AcDbSymbolTableRecord 167 | 100 168 | AcDbLinetypeTableRecord 169 | 2 170 | ByBlock 171 | 70 172 | 0 173 | 3 174 | 175 | 72 176 | 65 177 | 73 178 | 0 179 | 40 180 | 0.0 181 | 0 182 | LTYPE 183 | 5 184 | 15 185 | 330 186 | 5 187 | 100 188 | AcDbSymbolTableRecord 189 | 100 190 | AcDbLinetypeTableRecord 191 | 2 192 | ByLayer 193 | 70 194 | 0 195 | 3 196 | 197 | 72 198 | 65 199 | 73 200 | 0 201 | 40 202 | 0.0 203 | 0 204 | LTYPE 205 | 5 206 | 16 207 | 330 208 | 5 209 | 100 210 | AcDbSymbolTableRecord 211 | 100 212 | AcDbLinetypeTableRecord 213 | 2 214 | Continuous 215 | 70 216 | 0 217 | 3 218 | Solid line 219 | 72 220 | 65 221 | 73 222 | 0 223 | 40 224 | 0.0 225 | 0 226 | LTYPE 227 | 5 228 | 1A9 229 | 330 230 | 5 231 | 100 232 | AcDbSymbolTableRecord 233 | 100 234 | AcDbLinetypeTableRecord 235 | 2 236 | PHANTOM2 237 | 70 238 | 0 239 | 3 240 | Phantom (.5x) ___ _ _ ___ _ _ ___ _ _ ___ _ _ 241 | 72 242 | 65 243 | 73 244 | 6 245 | 40 246 | 1.25 247 | 49 248 | 0.625 249 | 74 250 | 0 251 | 49 252 | -0.125 253 | 74 254 | 0 255 | 49 256 | 0.125 257 | 74 258 | 0 259 | 49 260 | -0.125 261 | 74 262 | 0 263 | 49 264 | 0.125 265 | 74 266 | 0 267 | 49 268 | -0.125 269 | 74 270 | 0 271 | 0 272 | LTYPE 273 | 5 274 | 1C4 275 | 330 276 | 5 277 | 100 278 | AcDbSymbolTableRecord 279 | 100 280 | AcDbLinetypeTableRecord 281 | 2 282 | CENTER1 283 | 70 284 | 0 285 | 3 286 | Center (.5x) ___ _ ___ _ ___ _ ___ _ ___ _ ___ 287 | 72 288 | 65 289 | 73 290 | 4 291 | 40 292 | 1.125 293 | 49 294 | 0.75 295 | 74 296 | 0 297 | 49 298 | -0.125 299 | 74 300 | 0 301 | 49 302 | 0.125 303 | 74 304 | 0 305 | 49 306 | -0.125 307 | 74 308 | 0 309 | 0 310 | LTYPE 311 | 5 312 | 1C5 313 | 330 314 | 5 315 | 100 316 | AcDbSymbolTableRecord 317 | 100 318 | AcDbLinetypeTableRecord 319 | 2 320 | CENTER2 321 | 70 322 | 0 323 | 3 324 | Center (2x) ________ __ ________ __ _____ 325 | 72 326 | 65 327 | 73 328 | 4 329 | 40 330 | 4.0 331 | 49 332 | 2.5 333 | 74 334 | 0 335 | 49 336 | -0.5 337 | 74 338 | 0 339 | 49 340 | 0.5 341 | 74 342 | 0 343 | 49 344 | -0.5 345 | 74 346 | 0 347 | 0 348 | LTYPE 349 | 5 350 | 1C7 351 | 330 352 | 5 353 | 100 354 | AcDbSymbolTableRecord 355 | 100 356 | AcDbLinetypeTableRecord 357 | 2 358 | DASHDOT1 359 | 70 360 | 0 361 | 3 362 | Dash dot (.5x) _._._._._._._._._._._._._._._. 363 | 72 364 | 65 365 | 73 366 | 4 367 | 40 368 | 0.5 369 | 49 370 | 0.25 371 | 74 372 | 0 373 | 49 374 | -0.125 375 | 74 376 | 0 377 | 49 378 | 0.0 379 | 74 380 | 0 381 | 49 382 | -0.125 383 | 74 384 | 0 385 | 0 386 | LTYPE 387 | 5 388 | 1C8 389 | 330 390 | 5 391 | 100 392 | AcDbSymbolTableRecord 393 | 100 394 | AcDbLinetypeTableRecord 395 | 2 396 | DASHDOT2 397 | 70 398 | 0 399 | 3 400 | Dash dot (2x) ____ . ____ . ____ . ___ 401 | 72 402 | 65 403 | 73 404 | 4 405 | 40 406 | 2.0 407 | 49 408 | 1.0 409 | 74 410 | 0 411 | 49 412 | -0.5 413 | 74 414 | 0 415 | 49 416 | 0.0 417 | 74 418 | 0 419 | 49 420 | -0.5 421 | 74 422 | 0 423 | 0 424 | LTYPE 425 | 5 426 | 1CA 427 | 330 428 | 5 429 | 100 430 | AcDbSymbolTableRecord 431 | 100 432 | AcDbLinetypeTableRecord 433 | 2 434 | DASHED1 435 | 70 436 | 0 437 | 3 438 | Dashed (.5x) _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ 439 | 72 440 | 65 441 | 73 442 | 2 443 | 40 444 | 0.375 445 | 49 446 | 0.25 447 | 74 448 | 0 449 | 49 450 | -0.125 451 | 74 452 | 0 453 | 0 454 | LTYPE 455 | 5 456 | 1CB 457 | 330 458 | 5 459 | 100 460 | AcDbSymbolTableRecord 461 | 100 462 | AcDbLinetypeTableRecord 463 | 2 464 | DASHED2 465 | 70 466 | 0 467 | 3 468 | Dashed (2x) ____ ____ ____ ____ ____ ___ 469 | 72 470 | 65 471 | 73 472 | 2 473 | 40 474 | 1.5 475 | 49 476 | 1.0 477 | 74 478 | 0 479 | 49 480 | -0.5 481 | 74 482 | 0 483 | 0 484 | LTYPE 485 | 5 486 | 1CD 487 | 330 488 | 5 489 | 100 490 | AcDbSymbolTableRecord 491 | 100 492 | AcDbLinetypeTableRecord 493 | 2 494 | DOT1 495 | 70 496 | 0 497 | 3 498 | Dot (.5x) ..................................... 499 | 72 500 | 65 501 | 73 502 | 2 503 | 40 504 | 0.125 505 | 49 506 | 0.0 507 | 74 508 | 0 509 | 49 510 | -0.125 511 | 74 512 | 0 513 | 0 514 | LTYPE 515 | 5 516 | 1CE 517 | 330 518 | 5 519 | 100 520 | AcDbSymbolTableRecord 521 | 100 522 | AcDbLinetypeTableRecord 523 | 2 524 | DOT2 525 | 70 526 | 0 527 | 3 528 | Dot (2x) . . . . . . . . . . . . . 529 | 72 530 | 65 531 | 73 532 | 2 533 | 40 534 | 0.5 535 | 49 536 | 0.0 537 | 74 538 | 0 539 | 49 540 | -0.5 541 | 74 542 | 0 543 | 0 544 | ENDTAB 545 | 0 546 | TABLE 547 | 2 548 | LAYER 549 | 5 550 | 2 551 | 102 552 | {ACAD_XDICTIONARY 553 | 360 554 | 18E 555 | 102 556 | } 557 | 330 558 | 0 559 | 100 560 | AcDbSymbolTable 561 | 70 562 | 4 563 | 0 564 | LAYER 565 | 5 566 | 10 567 | 102 568 | {ACAD_XDICTIONARY 569 | 360 570 | E6 571 | 102 572 | } 573 | 330 574 | 2 575 | 100 576 | AcDbSymbolTableRecord 577 | 100 578 | AcDbLayerTableRecord 579 | 2 580 | 0 581 | 70 582 | 0 583 | 62 584 | 7 585 | 6 586 | Continuous 587 | 370 588 | -3 589 | 390 590 | F 591 | 347 592 | 98 593 | 348 594 | 0 595 | 0 596 | LAYER 597 | 5 598 | 1BD 599 | 330 600 | 2 601 | 100 602 | AcDbSymbolTableRecord 603 | 100 604 | AcDbLayerTableRecord 605 | 2 606 | Layer 1 607 | 70 608 | 5 609 | 62 610 | 7 611 | 6 612 | Continuous 613 | 370 614 | -3 615 | 390 616 | F 617 | 347 618 | 98 619 | 348 620 | 0 621 | 1001 622 | AcAecLayerStandard 623 | 1000 624 | 625 | 1000 626 | 627 | 1001 628 | AcCmTransparency 629 | 1071 630 | 0 631 | 0 632 | ENDTAB 633 | 0 634 | TABLE 635 | 2 636 | STYLE 637 | 5 638 | 3 639 | 330 640 | 0 641 | 100 642 | AcDbSymbolTable 643 | 70 644 | 2 645 | 0 646 | STYLE 647 | 5 648 | 11 649 | 330 650 | 3 651 | 100 652 | AcDbSymbolTableRecord 653 | 100 654 | AcDbTextStyleTableRecord 655 | 2 656 | Standard 657 | 70 658 | 0 659 | 40 660 | 0.0 661 | 41 662 | 1.0 663 | 50 664 | 0.0 665 | 71 666 | 0 667 | 42 668 | 0.2 669 | 3 670 | arial.ttf 671 | 4 672 | 673 | 1001 674 | ACAD 675 | 1000 676 | Arial 677 | 1071 678 | 34 679 | 0 680 | STYLE 681 | 5 682 | 225 683 | 330 684 | 3 685 | 100 686 | AcDbSymbolTableRecord 687 | 100 688 | AcDbTextStyleTableRecord 689 | 2 690 | Standard 360 691 | 70 692 | 0 693 | 40 694 | 0.0 695 | 41 696 | 1.0 697 | 50 698 | 0.0 699 | 71 700 | 0 701 | 42 702 | 0.2 703 | 3 704 | arial.ttf 705 | 4 706 | 707 | 1001 708 | ACAD 709 | 1000 710 | Arial 711 | 1071 712 | 0 713 | 0 714 | ENDTAB 715 | 0 716 | TABLE 717 | 2 718 | VIEW 719 | 5 720 | 6 721 | 330 722 | 0 723 | 100 724 | AcDbSymbolTable 725 | 70 726 | 0 727 | 0 728 | ENDTAB 729 | 0 730 | TABLE 731 | 2 732 | UCS 733 | 5 734 | 7 735 | 330 736 | 0 737 | 100 738 | AcDbSymbolTable 739 | 70 740 | 0 741 | 0 742 | ENDTAB 743 | 0 744 | TABLE 745 | 2 746 | APPID 747 | 5 748 | 9 749 | 330 750 | 0 751 | 100 752 | AcDbSymbolTable 753 | 70 754 | 11 755 | 0 756 | APPID 757 | 5 758 | 12 759 | 330 760 | 9 761 | 100 762 | AcDbSymbolTableRecord 763 | 100 764 | AcDbRegAppTableRecord 765 | 2 766 | ACAD 767 | 70 768 | 0 769 | 0 770 | APPID 771 | 5 772 | DD 773 | 330 774 | 9 775 | 100 776 | AcDbSymbolTableRecord 777 | 100 778 | AcDbRegAppTableRecord 779 | 2 780 | AcadAnnoPO 781 | 70 782 | 0 783 | 0 784 | APPID 785 | 5 786 | DE 787 | 330 788 | 9 789 | 100 790 | AcDbSymbolTableRecord 791 | 100 792 | AcDbRegAppTableRecord 793 | 2 794 | AcadAnnotative 795 | 70 796 | 0 797 | 0 798 | APPID 799 | 5 800 | DF 801 | 330 802 | 9 803 | 100 804 | AcDbSymbolTableRecord 805 | 100 806 | AcDbRegAppTableRecord 807 | 2 808 | ACAD_DSTYLE_DIMJAG 809 | 70 810 | 0 811 | 0 812 | APPID 813 | 5 814 | E0 815 | 330 816 | 9 817 | 100 818 | AcDbSymbolTableRecord 819 | 100 820 | AcDbRegAppTableRecord 821 | 2 822 | ACAD_DSTYLE_DIMTALN 823 | 70 824 | 0 825 | 0 826 | APPID 827 | 5 828 | 107 829 | 330 830 | 9 831 | 100 832 | AcDbSymbolTableRecord 833 | 100 834 | AcDbRegAppTableRecord 835 | 2 836 | ACAD_MLEADERVER 837 | 70 838 | 0 839 | 0 840 | APPID 841 | 5 842 | 1A6 843 | 330 844 | 9 845 | 100 846 | AcDbSymbolTableRecord 847 | 100 848 | AcDbRegAppTableRecord 849 | 2 850 | ACAD_NAV_VCDISPLAY 851 | 70 852 | 0 853 | 0 854 | APPID 855 | 5 856 | 1BE 857 | 330 858 | 9 859 | 100 860 | AcDbSymbolTableRecord 861 | 100 862 | AcDbRegAppTableRecord 863 | 2 864 | AcAecLayerStandard 865 | 70 866 | 0 867 | 0 868 | APPID 869 | 5 870 | 1BF 871 | 330 872 | 9 873 | 100 874 | AcDbSymbolTableRecord 875 | 100 876 | AcDbRegAppTableRecord 877 | 2 878 | AcCmTransparency 879 | 70 880 | 0 881 | 0 882 | APPID 883 | 5 884 | 1CF 885 | 330 886 | 9 887 | 100 888 | AcDbSymbolTableRecord 889 | 100 890 | AcDbRegAppTableRecord 891 | 2 892 | ACAD_EXEMPT_FROM_CAD_STANDARDS 893 | 70 894 | 0 895 | 0 896 | APPID 897 | 5 898 | 1FB 899 | 330 900 | 9 901 | 100 902 | AcDbSymbolTableRecord 903 | 100 904 | AcDbRegAppTableRecord 905 | 2 906 | ACAD_PSEXT 907 | 70 908 | 0 909 | 0 910 | ENDTAB 911 | 0 912 | TABLE 913 | 2 914 | DIMSTYLE 915 | 5 916 | A 917 | 330 918 | 0 919 | 100 920 | AcDbSymbolTable 921 | 70 922 | 2 923 | 100 924 | AcDbDimStyleTable 925 | 71 926 | 1 927 | 340 928 | 27 929 | 0 930 | DIMSTYLE 931 | 105 932 | 27 933 | 330 934 | A 935 | 100 936 | AcDbSymbolTableRecord 937 | 100 938 | AcDbDimStyleTableRecord 939 | 2 940 | Standard 941 | 70 942 | 0 943 | 340 944 | 11 945 | 0 946 | DIMSTYLE 947 | 105 948 | 226 949 | 330 950 | A 951 | 100 952 | AcDbSymbolTableRecord 953 | 100 954 | AcDbDimStyleTableRecord 955 | 2 956 | Standard 360 957 | 70 958 | 0 959 | 41 960 | 1.0 961 | 73 962 | 0 963 | 77 964 | 1 965 | 140 966 | 1.0 967 | 340 968 | 225 969 | 0 970 | ENDTAB 971 | 0 972 | TABLE 973 | 2 974 | BLOCK_RECORD 975 | 5 976 | 1 977 | 330 978 | 0 979 | 100 980 | AcDbSymbolTable 981 | 70 982 | 1 983 | 0 984 | BLOCK_RECORD 985 | 5 986 | 1F 987 | 102 988 | {ACAD_XDICTIONARY 989 | 360 990 | 15D 991 | 102 992 | } 993 | 330 994 | 1 995 | 100 996 | AcDbSymbolTableRecord 997 | 100 998 | AcDbBlockTableRecord 999 | 2 1000 | *Model_Space 1001 | 340 1002 | 22 1003 | 70 1004 | 0 1005 | 280 1006 | 1 1007 | 281 1008 | 0 1009 | 0 1010 | BLOCK_RECORD 1011 | 5 1012 | 5D 1013 | 330 1014 | 1 1015 | 100 1016 | AcDbSymbolTableRecord 1017 | 100 1018 | AcDbBlockTableRecord 1019 | 2 1020 | *Paper_Space 1021 | 340 1022 | 5E 1023 | 70 1024 | 0 1025 | 280 1026 | 1 1027 | 281 1028 | 0 1029 | 0 1030 | BLOCK_RECORD 1031 | 5 1032 | 58 1033 | 330 1034 | 1 1035 | 100 1036 | AcDbSymbolTableRecord 1037 | 100 1038 | AcDbBlockTableRecord 1039 | 2 1040 | *Paper_Space0 1041 | 340 1042 | 59 1043 | 70 1044 | 0 1045 | 280 1046 | 1 1047 | 281 1048 | 0 1049 | 0 1050 | ENDTAB 1051 | 0 1052 | ENDSEC 1053 | 0 1054 | EOF -------------------------------------------------------------------------------- /test/data/viewport-table.expected.json: -------------------------------------------------------------------------------- 1 | { 2 | "handle": "8", 3 | "ownerHandle": "0", 4 | "viewPorts": [ 5 | { 6 | "ownerHandle": "8", 7 | "name": "*Active", 8 | "lowerLeftCorner": { 9 | "x": 0, 10 | "y": 0 11 | }, 12 | "upperRightCorner": { 13 | "x": 1, 14 | "y": 1 15 | }, 16 | "center": { 17 | "x": 23.34842155490301, 18 | "y": 8.680283835098335 19 | }, 20 | "snapBasePoint": { 21 | "x": 0, 22 | "y": 0 23 | }, 24 | "snapSpacing": { 25 | "x": 0.5, 26 | "y": 0.5 27 | }, 28 | "gridSpacing": { 29 | "x": 0.5, 30 | "y": 0.5 31 | }, 32 | "viewDirectionFromTarget": { 33 | "x": 0, 34 | "y": 0, 35 | "z": 1 36 | }, 37 | "viewTarget": { 38 | "x": 0, 39 | "y": 0, 40 | "z": 0 41 | }, 42 | "lensLength": 50, 43 | "frontClippingPlane": 0, 44 | "backClippingPlane": 0, 45 | "snapRotationAngle": 0, 46 | "viewTwistAngle": 0, 47 | "renderMode": 0, 48 | "ucsOrigin": { 49 | "x": 0, 50 | "y": 0, 51 | "z": 0 52 | }, 53 | "ucsXAxis": { 54 | "x": 1, 55 | "y": 0, 56 | "z": 0 57 | }, 58 | "ucsYAxis": { 59 | "x": 0, 60 | "y": 1, 61 | "z": 0 62 | }, 63 | "orthographicType": 0, 64 | "defaultLightingOn": true, 65 | "ambientColor": 3355443 66 | } 67 | ] 68 | } -------------------------------------------------------------------------------- /tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "exclude": [], 3 | "include": [ 4 | "./src/**/*.ts" 5 | ], 6 | "compileOnSave": false, 7 | "compilerOptions": { 8 | "module": "es2015", 9 | "target": "esnext", 10 | "jsx": "react", 11 | "noImplicitAny": true, 12 | "sourceMap": false, 13 | "emitDecoratorMetadata": true, 14 | "experimentalDecorators": true, 15 | "strictNullChecks": true, 16 | "noImplicitThis": true, 17 | "rootDir": "./src", 18 | "outDir": "./esm/", 19 | "allowJs": false, 20 | "allowUnreachableCode": false, 21 | "allowUnusedLabels": false, 22 | "alwaysStrict": true, 23 | "baseUrl": "", 24 | "charset": "utf8", 25 | "declaration": true, 26 | "inlineSourceMap": false, 27 | "esModuleInterop": true, 28 | "allowSyntheticDefaultImports": true, 29 | "diagnostics": false, 30 | "emitBOM": false, 31 | "forceConsistentCasingInFileNames": false, 32 | "importHelpers": false, 33 | "inlineSources": false, 34 | "isolatedModules": false, 35 | "lib": [ 36 | "esnext" 37 | ], 38 | "listFiles": false, 39 | "listEmittedFiles": false, 40 | "locale": "zh_CN", 41 | "newLine": "lf", 42 | "noEmit": false, 43 | "moduleResolution": "node", 44 | "noEmitHelpers": false, 45 | "noEmitOnError": false, 46 | "noImplicitReturns": true, 47 | "noImplicitUseStrict": false, 48 | "maxNodeModuleJsDepth": 0, 49 | "noLib": false, 50 | "noFallthroughCasesInSwitch": true, 51 | "noResolve": false, 52 | "noUnusedLocals": true, 53 | "noUnusedParameters": true, 54 | "paths": {}, 55 | "preserveConstEnums": false, 56 | "pretty": true, 57 | "removeComments": false, 58 | "skipDefaultLibCheck": true, 59 | "skipLibCheck": true, 60 | "stripInternal": false, 61 | "suppressExcessPropertyErrors": false, 62 | "suppressImplicitAnyIndexErrors": true, 63 | "traceResolution": false, 64 | "typeRoots": [], 65 | "types": [ 66 | "node" 67 | ], 68 | "watch": false 69 | } 70 | } -------------------------------------------------------------------------------- /webpack.config.js: -------------------------------------------------------------------------------- 1 | import { resolve, dirname } from 'path'; 2 | 3 | export default { 4 | entry: './esm/index.js', 5 | output: { 6 | filename: 'index.js', 7 | path: resolve(dirname(new URL(import.meta.url).pathname), 'commonjs'), 8 | library: { 9 | name: 'DxfParser', 10 | type: 'umd', 11 | export: 'DxfParser' 12 | }, 13 | globalObject: 'typeof self !== \'undefined\' ? self : this' 14 | } 15 | }; 16 | --------------------------------------------------------------------------------