You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
2405 lines
66 KiB
2405 lines
66 KiB
2 years ago
|
(function(f){if(typeof exports==="object"&&typeof module!=="undefined"){module.exports=f()}else if(typeof define==="function"&&define.amd){define([],f)}else{var g;if(typeof window!=="undefined"){g=window}else if(typeof global!=="undefined"){g=global}else if(typeof self!=="undefined"){g=self}else{g=this}g.DxfParser = f()}})(function(){var define,module,exports;return (function e(t,n,r){function s(o,u){if(!n[o]){if(!t[o]){var a=typeof require=="function"&&require;if(!u&&a)return a(o,!0);if(i)return i(o,!0);var f=new Error("Cannot find module '"+o+"'");throw f.code="MODULE_NOT_FOUND",f}var l=n[o]={exports:{}};t[o][0].call(l.exports,function(e){var n=t[o][1][e];return s(n?n:e)},l,l.exports,e,t,n,r)}return n[o].exports}var i=typeof require=="function"&&require;for(var o=0;o<r.length;o++)s(r[o]);return s})({1:[function(require,module,exports){
|
||
|
/**
|
||
|
* AutoCad files sometimes use an indexed color value between 1 and 255 inclusive.
|
||
|
* Each value corresponds to a color. index 1 is red, that is 16711680 or 0xFF0000.
|
||
|
* index 0 and 256, while included in this array, are actually reserved for inheritance
|
||
|
* values in AutoCad so they should not be used for index color lookups.
|
||
|
*/
|
||
|
|
||
|
module.exports = [
|
||
|
0,
|
||
|
16711680,
|
||
|
16776960,
|
||
|
65280,
|
||
|
65535,
|
||
|
255,
|
||
|
16711935,
|
||
|
16777215,
|
||
|
8421504,
|
||
|
12632256,
|
||
|
16711680,
|
||
|
16744319,
|
||
|
13369344,
|
||
|
13395558,
|
||
|
10027008,
|
||
|
10046540,
|
||
|
8323072,
|
||
|
8339263,
|
||
|
4980736,
|
||
|
4990502,
|
||
|
16727808,
|
||
|
16752511,
|
||
|
13382400,
|
||
|
13401958,
|
||
|
10036736,
|
||
|
10051404,
|
||
|
8331008,
|
||
|
8343359,
|
||
|
4985600,
|
||
|
4992806,
|
||
|
16744192,
|
||
|
16760703,
|
||
|
13395456,
|
||
|
13408614,
|
||
|
10046464,
|
||
|
10056268,
|
||
|
8339200,
|
||
|
8347455,
|
||
|
4990464,
|
||
|
4995366,
|
||
|
16760576,
|
||
|
16768895,
|
||
|
13408512,
|
||
|
13415014,
|
||
|
10056192,
|
||
|
10061132,
|
||
|
8347392,
|
||
|
8351551,
|
||
|
4995328,
|
||
|
4997670,
|
||
|
16776960,
|
||
|
16777087,
|
||
|
13421568,
|
||
|
13421670,
|
||
|
10000384,
|
||
|
10000460,
|
||
|
8355584,
|
||
|
8355647,
|
||
|
5000192,
|
||
|
5000230,
|
||
|
12582656,
|
||
|
14679935,
|
||
|
10079232,
|
||
|
11717734,
|
||
|
7510016,
|
||
|
8755276,
|
||
|
6258432,
|
||
|
7307071,
|
||
|
3755008,
|
||
|
4344870,
|
||
|
8388352,
|
||
|
12582783,
|
||
|
6736896,
|
||
|
10079334,
|
||
|
5019648,
|
||
|
7510092,
|
||
|
4161280,
|
||
|
6258495,
|
||
|
2509824,
|
||
|
3755046,
|
||
|
4194048,
|
||
|
10485631,
|
||
|
3394560,
|
||
|
8375398,
|
||
|
2529280,
|
||
|
6264908,
|
||
|
2064128,
|
||
|
5209919,
|
||
|
1264640,
|
||
|
3099686,
|
||
|
65280,
|
||
|
8388479,
|
||
|
52224,
|
||
|
6736998,
|
||
|
38912,
|
||
|
5019724,
|
||
|
32512,
|
||
|
4161343,
|
||
|
19456,
|
||
|
2509862,
|
||
|
65343,
|
||
|
8388511,
|
||
|
52275,
|
||
|
6737023,
|
||
|
38950,
|
||
|
5019743,
|
||
|
32543,
|
||
|
4161359,
|
||
|
19475,
|
||
|
2509871,
|
||
|
65407,
|
||
|
8388543,
|
||
|
52326,
|
||
|
6737049,
|
||
|
38988,
|
||
|
5019762,
|
||
|
32575,
|
||
|
4161375,
|
||
|
19494,
|
||
|
2509881,
|
||
|
65471,
|
||
|
8388575,
|
||
|
52377,
|
||
|
6737074,
|
||
|
39026,
|
||
|
5019781,
|
||
|
32607,
|
||
|
4161391,
|
||
|
19513,
|
||
|
2509890,
|
||
|
65535,
|
||
|
8388607,
|
||
|
52428,
|
||
|
6737100,
|
||
|
39064,
|
||
|
5019800,
|
||
|
32639,
|
||
|
4161407,
|
||
|
19532,
|
||
|
2509900,
|
||
|
49151,
|
||
|
8380415,
|
||
|
39372,
|
||
|
6730444,
|
||
|
29336,
|
||
|
5014936,
|
||
|
24447,
|
||
|
4157311,
|
||
|
14668,
|
||
|
2507340,
|
||
|
32767,
|
||
|
8372223,
|
||
|
26316,
|
||
|
6724044,
|
||
|
19608,
|
||
|
5010072,
|
||
|
16255,
|
||
|
4153215,
|
||
|
9804,
|
||
|
2505036,
|
||
|
16383,
|
||
|
8364031,
|
||
|
13260,
|
||
|
6717388,
|
||
|
9880,
|
||
|
5005208,
|
||
|
8063,
|
||
|
4149119,
|
||
|
4940,
|
||
|
2502476,
|
||
|
255,
|
||
|
8355839,
|
||
|
204,
|
||
|
6710988,
|
||
|
152,
|
||
|
5000344,
|
||
|
127,
|
||
|
4145023,
|
||
|
76,
|
||
|
2500172,
|
||
|
4129023,
|
||
|
10452991,
|
||
|
3342540,
|
||
|
8349388,
|
||
|
2490520,
|
||
|
6245528,
|
||
|
2031743,
|
||
|
5193599,
|
||
|
1245260,
|
||
|
3089996,
|
||
|
8323327,
|
||
|
12550143,
|
||
|
6684876,
|
||
|
10053324,
|
||
|
4980888,
|
||
|
7490712,
|
||
|
4128895,
|
||
|
6242175,
|
||
|
2490444,
|
||
|
3745356,
|
||
|
12517631,
|
||
|
14647295,
|
||
|
10027212,
|
||
|
11691724,
|
||
|
7471256,
|
||
|
8735896,
|
||
|
6226047,
|
||
|
7290751,
|
||
|
3735628,
|
||
|
4335180,
|
||
|
16711935,
|
||
|
16744447,
|
||
|
13369548,
|
||
|
13395660,
|
||
|
9961624,
|
||
|
9981080,
|
||
|
8323199,
|
||
|
8339327,
|
||
|
4980812,
|
||
|
4990540,
|
||
|
16711871,
|
||
|
16744415,
|
||
|
13369497,
|
||
|
13395634,
|
||
|
9961586,
|
||
|
9981061,
|
||
|
8323167,
|
||
|
8339311,
|
||
|
4980793,
|
||
|
4990530,
|
||
|
16711807,
|
||
|
16744383,
|
||
|
13369446,
|
||
|
13395609,
|
||
|
9961548,
|
||
|
9981042,
|
||
|
8323135,
|
||
|
8339295,
|
||
|
4980774,
|
||
|
4990521,
|
||
|
16711743,
|
||
|
16744351,
|
||
|
13369395,
|
||
|
13395583,
|
||
|
9961510,
|
||
|
9981023,
|
||
|
8323103,
|
||
|
8339279,
|
||
|
4980755,
|
||
|
4990511,
|
||
|
3355443,
|
||
|
5987163,
|
||
|
8684676,
|
||
|
11382189,
|
||
|
14079702,
|
||
|
16777215
|
||
|
];
|
||
|
},{}],2:[function(require,module,exports){
|
||
|
/**
|
||
|
* DxfArrayScanner
|
||
|
*
|
||
|
* Based off the AutoCad 2012 DXF Reference
|
||
|
* http://images.autodesk.com/adsk/files/autocad_2012_pdf_dxf-reference_enu.pdf
|
||
|
*
|
||
|
* Reads through an array representing lines of a dxf file. Takes an array and
|
||
|
* provides an easy interface to extract group code and value pairs.
|
||
|
* @param data - an array where each element represents a line in the dxf file
|
||
|
* @constructor
|
||
|
*/
|
||
|
function DxfArrayScanner(data) {
|
||
|
this._pointer = 0;
|
||
|
this._data = data;
|
||
|
this._eof = false;
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Gets the next group (code, value) from the array. A group is two consecutive elements
|
||
|
* in the array. The first is the code, the second is the value.
|
||
|
* @returns {{code: Number}|*}
|
||
|
*/
|
||
|
DxfArrayScanner.prototype.next = function() {
|
||
|
var group;
|
||
|
if(!this.hasNext()) {
|
||
|
if(!this._eof)
|
||
|
throw new Error('Unexpected end of input: EOF group not read before end of file. Ended on code ' + this._data[this._pointer]);
|
||
|
else
|
||
|
throw new Error('Cannot call \'next\' after EOF group has been read');
|
||
|
}
|
||
|
|
||
|
group = {
|
||
|
code: parseInt(this._data[this._pointer])
|
||
|
};
|
||
|
|
||
|
this._pointer++;
|
||
|
|
||
|
group.value = parseGroupValue(group.code, this._data[this._pointer].trim());
|
||
|
|
||
|
this._pointer++;
|
||
|
|
||
|
if(group.code === 0 && group.value === 'EOF') this._eof = true;
|
||
|
|
||
|
this.lastReadGroup = group;
|
||
|
|
||
|
return group;
|
||
|
};
|
||
|
|
||
|
DxfArrayScanner.prototype.peek = function() {
|
||
|
if(!this.hasNext()) {
|
||
|
if(!this._eof)
|
||
|
throw new Error('Unexpected end of input: EOF group not read before end of file. Ended on code ' + this._data[this._pointer]);
|
||
|
else
|
||
|
throw new Error('Cannot call \'next\' after EOF group has been read');
|
||
|
}
|
||
|
|
||
|
var group = {
|
||
|
code: parseInt(this._data[this._pointer])
|
||
|
};
|
||
|
|
||
|
group.value = parseGroupValue(group.code, this._data[this._pointer + 1].trim());
|
||
|
|
||
|
return group;
|
||
|
};
|
||
|
|
||
|
|
||
|
DxfArrayScanner.prototype.rewind = function(numberOfGroups) {
|
||
|
numberOfGroups = numberOfGroups || 1;
|
||
|
this._pointer = this._pointer - numberOfGroups * 2;
|
||
|
};
|
||
|
|
||
|
/**
|
||
|
* Returns true if there is another code/value pair (2 elements in the array).
|
||
|
* @returns {boolean}
|
||
|
*/
|
||
|
DxfArrayScanner.prototype.hasNext = function() {
|
||
|
// Check if we have read EOF group code
|
||
|
if(this._eof) {
|
||
|
return false;
|
||
|
}
|
||
|
|
||
|
// We need to be sure there are two lines available
|
||
|
if(this._pointer > this._data.length - 2) {
|
||
|
return false;
|
||
|
}
|
||
|
return true;
|
||
|
};
|
||
|
|
||
|
/**
|
||
|
* Returns true if the scanner is at the end of the array
|
||
|
* @returns {boolean}
|
||
|
*/
|
||
|
DxfArrayScanner.prototype.isEOF = function() {
|
||
|
return this._eof;
|
||
|
};
|
||
|
|
||
|
/**
|
||
|
* Parse a value to its proper type.
|
||
|
* See pages 3 - 10 of the AutoCad DXF 2012 reference given at the top of this file
|
||
|
*
|
||
|
* @param code
|
||
|
* @param value
|
||
|
* @returns {*}
|
||
|
*/
|
||
|
function parseGroupValue(code, value) {
|
||
|
if(code <= 9) return value;
|
||
|
if(code >= 10 && code <= 59) return parseFloat(value);
|
||
|
if(code >= 60 && code <= 99) return parseInt(value);
|
||
|
if(code >= 100 && code <= 109) return value;
|
||
|
if(code >= 110 && code <= 149) return parseFloat(value);
|
||
|
if(code >= 160 && code <= 179) return parseInt(value);
|
||
|
if(code >= 210 && code <= 239) return parseFloat(value);
|
||
|
if(code >= 270 && code <= 289) return parseInt(value);
|
||
|
if(code >= 290 && code <= 299) return parseBoolean(value);
|
||
|
if(code >= 300 && code <= 369) return value;
|
||
|
if(code >= 370 && code <= 389) return parseInt(value);
|
||
|
if(code >= 390 && code <= 399) return value;
|
||
|
if(code >= 400 && code <= 409) return parseInt(value);
|
||
|
if(code >= 410 && code <= 419) return value;
|
||
|
if(code >= 420 && code <= 429) return parseInt(value);
|
||
|
if(code >= 430 && code <= 439) return value;
|
||
|
if(code >= 440 && code <= 459) return parseInt(value);
|
||
|
if(code >= 460 && code <= 469) return parseFloat(value);
|
||
|
if(code >= 470 && code <= 481) return value;
|
||
|
if(code === 999) return value;
|
||
|
if(code >= 1000 && code <= 1009) return value;
|
||
|
if(code >= 1010 && code <= 1059) return parseFloat(value);
|
||
|
if(code >= 1060 && code <= 1071) return parseInt(value);
|
||
|
|
||
|
console.log('WARNING: Group code does not have a defined type: %j', { code: code, value: value });
|
||
|
return value;
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Parse a boolean according to a 1 or 0 value
|
||
|
* @param str
|
||
|
* @returns {boolean}
|
||
|
*/
|
||
|
function parseBoolean(str) {
|
||
|
if(str === '0') return false;
|
||
|
if(str === '1') return true;
|
||
|
throw TypeError('String \'' + str + '\' cannot be cast to Boolean type');
|
||
|
}
|
||
|
|
||
|
module.exports = DxfArrayScanner;
|
||
|
},{}],3:[function(require,module,exports){
|
||
|
var DxfArrayScanner = require('./DxfArrayScanner.js'),
|
||
|
AUTO_CAD_COLOR_INDEX = require('./AutoCadColorIndex');
|
||
|
|
||
|
var log = require('loglevel');
|
||
|
|
||
|
//log.setLevel('trace');
|
||
|
//log.setLevel('debug');
|
||
|
//log.setLevel('info');
|
||
|
//log.setLevel('warn');
|
||
|
log.setLevel('error');
|
||
|
//log.setLevel('silent');
|
||
|
|
||
|
function registerDefaultEntityHandlers(dxfParser) {
|
||
|
// Supported entities here (some entity code is still being refactored into this flow)
|
||
|
dxfParser.registerEntityHandler(require('./entities/3dface'));
|
||
|
dxfParser.registerEntityHandler(require('./entities/arc'));
|
||
|
dxfParser.registerEntityHandler(require('./entities/attdef'));
|
||
|
dxfParser.registerEntityHandler(require('./entities/circle'));
|
||
|
dxfParser.registerEntityHandler(require('./entities/dimension'));
|
||
|
dxfParser.registerEntityHandler(require('./entities/ellipse'));
|
||
|
dxfParser.registerEntityHandler(require('./entities/insert'));
|
||
|
dxfParser.registerEntityHandler(require('./entities/line'));
|
||
|
dxfParser.registerEntityHandler(require('./entities/lwpolyline'));
|
||
|
dxfParser.registerEntityHandler(require('./entities/mtext'));
|
||
|
dxfParser.registerEntityHandler(require('./entities/point'));
|
||
|
dxfParser.registerEntityHandler(require('./entities/polyline'));
|
||
|
dxfParser.registerEntityHandler(require('./entities/solid'));
|
||
|
dxfParser.registerEntityHandler(require('./entities/spline'));
|
||
|
dxfParser.registerEntityHandler(require('./entities/text'));
|
||
|
//dxfParser.registerEntityHandler(require('./entities/vertex'));
|
||
|
}
|
||
|
|
||
|
function DxfParser() {
|
||
|
this._entityHandlers = {};
|
||
|
|
||
|
registerDefaultEntityHandlers(this);
|
||
|
}
|
||
|
|
||
|
DxfParser.prototype.parse = function(source, done) {
|
||
|
throw new Error("read() not implemented. Use readSync()");
|
||
|
};
|
||
|
|
||
|
DxfParser.prototype.registerEntityHandler = function(handlerType) {
|
||
|
var instance = new handlerType();
|
||
|
this._entityHandlers[handlerType.ForEntityName] = instance;
|
||
|
}
|
||
|
|
||
|
DxfParser.prototype.parseSync = function(source) {
|
||
|
if(typeof(source) === 'string') {
|
||
|
return this._parse(source);
|
||
|
}else {
|
||
|
console.error('Cannot read dxf source of type `' + typeof(source));
|
||
|
return null;
|
||
|
}
|
||
|
};
|
||
|
|
||
|
DxfParser.prototype.parseStream = function(stream, done) {
|
||
|
|
||
|
var dxfString = "";
|
||
|
var self = this;
|
||
|
|
||
|
stream.on('data', onData);
|
||
|
stream.on('end', onEnd);
|
||
|
stream.on('error', onError);
|
||
|
|
||
|
function onData(chunk) {
|
||
|
dxfString += chunk;
|
||
|
}
|
||
|
|
||
|
function onEnd() {
|
||
|
try {
|
||
|
var dxf = self._parse(dxfString);
|
||
|
}catch(err) {
|
||
|
return done(err);
|
||
|
}
|
||
|
done(null, dxf);
|
||
|
}
|
||
|
|
||
|
function onError(err) {
|
||
|
done(err);
|
||
|
}
|
||
|
};
|
||
|
|
||
|
DxfParser.prototype._parse = function(dxfString) {
|
||
|
var scanner, curr, dxf = {}, lastHandle = 0;
|
||
|
var dxfLinesArray = dxfString.split(/\r\n|\r|\n/g);
|
||
|
|
||
|
scanner = new DxfArrayScanner(dxfLinesArray);
|
||
|
if(!scanner.hasNext()) throw Error('Empty file');
|
||
|
|
||
|
var self = this;
|
||
|
|
||
|
var parseAll = function() {
|
||
|
curr = scanner.next();
|
||
|
while(!scanner.isEOF()) {
|
||
|
if(curr.code === 0 && curr.value === 'SECTION') {
|
||
|
curr = scanner.next();
|
||
|
|
||
|
// Be sure we are reading a section code
|
||
|
if (curr.code !== 2) {
|
||
|
console.error('Unexpected code %s after 0:SECTION', debugCode(curr));
|
||
|
curr = scanner.next();
|
||
|
continue;
|
||
|
}
|
||
|
|
||
|
if (curr.value === 'HEADER') {
|
||
|
log.debug('> HEADER');
|
||
|
dxf.header = parseHeader();
|
||
|
log.debug('<');
|
||
|
} else if (curr.value === 'BLOCKS') {
|
||
|
log.debug('> BLOCKS');
|
||
|
dxf.blocks = parseBlocks();
|
||
|
log.debug('<');
|
||
|
} else if(curr.value === 'ENTITIES') {
|
||
|
log.debug('> ENTITIES');
|
||
|
dxf.entities = parseEntities(false);
|
||
|
log.debug('<');
|
||
|
} else if(curr.value === 'TABLES') {
|
||
|
log.debug('> TABLES');
|
||
|
dxf.tables = parseTables();
|
||
|
log.debug('<');
|
||
|
} else if(curr.value === 'EOF') {
|
||
|
log.debug('EOF');
|
||
|
} else {
|
||
|
log.warn('Skipping section \'%s\'', curr.value);
|
||
|
}
|
||
|
} else {
|
||
|
curr = scanner.next();
|
||
|
}
|
||
|
// If is a new section
|
||
|
}
|
||
|
};
|
||
|
|
||
|
var groupIs = function(code, value) {
|
||
|
return curr.code === code && curr.value === value;
|
||
|
};
|
||
|
|
||
|
/**
|
||
|
*
|
||
|
* @return {object} header
|
||
|
*/
|
||
|
var parseHeader = function() {
|
||
|
// interesting variables:
|
||
|
// $ACADVER, $VIEWDIR, $VIEWSIZE, $VIEWCTR, $TDCREATE, $TDUPDATE
|
||
|
// http://www.autodesk.com/techpubs/autocad/acadr14/dxf/header_section_al_u05_c.htm
|
||
|
// Also see VPORT table entries
|
||
|
var currVarName = null, currVarValue = null;
|
||
|
var header = {};
|
||
|
// loop through header variables
|
||
|
curr = scanner.next();
|
||
|
|
||
|
while(true) {
|
||
|
if(groupIs(0, 'ENDSEC')) {
|
||
|
if(currVarName) header[currVarName] = currVarValue;
|
||
|
break;
|
||
|
} else if(curr.code === 9) {
|
||
|
if(currVarName) header[currVarName] = currVarValue;
|
||
|
currVarName = curr.value;
|
||
|
// Filter here for particular variables we are interested in
|
||
|
} else {
|
||
|
if(curr.code === 10) {
|
||
|
currVarValue = { x: curr.value };
|
||
|
} else if(curr.code === 20) {
|
||
|
currVarValue.y = curr.value;
|
||
|
} else if(curr.code === 30) {
|
||
|
currVarValue.z = curr.value;
|
||
|
} else {
|
||
|
currVarValue = curr.value;
|
||
|
}
|
||
|
}
|
||
|
curr = scanner.next();
|
||
|
}
|
||
|
// console.log(util.inspect(header, { colors: true, depth: null }));
|
||
|
curr = scanner.next(); // swallow up ENDSEC
|
||
|
return header;
|
||
|
};
|
||
|
|
||
|
|
||
|
/**
|
||
|
*
|
||
|
*/
|
||
|
var parseBlocks = function() {
|
||
|
var blocks = {}, block;
|
||
|
|
||
|
curr = scanner.next();
|
||
|
|
||
|
while(curr.value !== 'EOF') {
|
||
|
if(groupIs(0, 'ENDSEC')) {
|
||
|
break;
|
||
|
}
|
||
|
|
||
|
if(groupIs(0, 'BLOCK')) {
|
||
|
log.debug('block {');
|
||
|
block = parseBlock();
|
||
|
log.debug('}');
|
||
|
ensureHandle(block);
|
||
|
if(!block.name)
|
||
|
log.error('block with handle "' + block.handle + '" is missing a name.');
|
||
|
else
|
||
|
blocks[block.name] = block;
|
||
|
} else {
|
||
|
logUnhandledGroup(curr);
|
||
|
curr = scanner.next();
|
||
|
}
|
||
|
}
|
||
|
return blocks;
|
||
|
};
|
||
|
|
||
|
var parseBlock = function() {
|
||
|
var block = {};
|
||
|
curr = scanner.next();
|
||
|
|
||
|
while(curr.value !== 'EOF') {
|
||
|
switch(curr.code) {
|
||
|
case 1:
|
||
|
block.xrefPath = curr.value;
|
||
|
curr = scanner.next();
|
||
|
break;
|
||
|
case 2:
|
||
|
block.name = curr.value;
|
||
|
curr = scanner.next();
|
||
|
break;
|
||
|
case 3:
|
||
|
block.name2 = curr.value;
|
||
|
curr = scanner.next();
|
||
|
break;
|
||
|
case 5:
|
||
|
block.handle = curr.value;
|
||
|
curr = scanner.next();
|
||
|
break;
|
||
|
case 8:
|
||
|
block.layer = curr.value;
|
||
|
curr = scanner.next();
|
||
|
break;
|
||
|
case 10:
|
||
|
block.position = parsePoint();
|
||
|
curr = scanner.next();
|
||
|
break;
|
||
|
case 67:
|
||
|
block.paperSpace = (curr.value && curr.value == 1) ? true : false;
|
||
|
curr = scanner.next();
|
||
|
break;
|
||
|
case 70:
|
||
|
if (curr.value != 0) {
|
||
|
//if(curr.value & BLOCK_ANONYMOUS_FLAG) console.log(' Anonymous block');
|
||
|
//if(curr.value & BLOCK_NON_CONSTANT_FLAG) console.log(' Non-constant attributes');
|
||
|
//if(curr.value & BLOCK_XREF_FLAG) console.log(' Is xref');
|
||
|
//if(curr.value & BLOCK_XREF_OVERLAY_FLAG) console.log(' Is xref overlay');
|
||
|
//if(curr.value & BLOCK_EXTERNALLY_DEPENDENT_FLAG) console.log(' Is externally dependent');
|
||
|
//if(curr.value & BLOCK_RESOLVED_OR_DEPENDENT_FLAG) console.log(' Is resolved xref or dependent of an xref');
|
||
|
//if(curr.value & BLOCK_REFERENCED_XREF) console.log(' This definition is a referenced xref');
|
||
|
block.type = curr.value;
|
||
|
}
|
||
|
curr = scanner.next();
|
||
|
break;
|
||
|
case 100:
|
||
|
// ignore class markers
|
||
|
curr = scanner.next();
|
||
|
break;
|
||
|
case 330:
|
||
|
block.ownerHandle = curr.value;
|
||
|
curr = scanner.next();
|
||
|
break;
|
||
|
case 0:
|
||
|
if(curr.value == 'ENDBLK')
|
||
|
break;
|
||
|
block.entities = parseEntities(true);
|
||
|
break;
|
||
|
default:
|
||
|
logUnhandledGroup(curr);
|
||
|
curr = scanner.next();
|
||
|
}
|
||
|
|
||
|
if(groupIs(0, 'ENDBLK')) {
|
||
|
curr = scanner.next();
|
||
|
break;
|
||
|
}
|
||
|
}
|
||
|
return block;
|
||
|
};
|
||
|
|
||
|
/**
|
||
|
* parseTables
|
||
|
* @return {Object} Object representing tables
|
||
|
*/
|
||
|
var parseTables = function() {
|
||
|
var tables = {};
|
||
|
curr = scanner.next();
|
||
|
while(curr.value !== 'EOF') {
|
||
|
if(groupIs(0, 'ENDSEC'))
|
||
|
break;
|
||
|
|
||
|
if(groupIs(0, 'TABLE')) {
|
||
|
curr = scanner.next();
|
||
|
|
||
|
var tableDefinition = tableDefinitions[curr.value];
|
||
|
if(tableDefinition) {
|
||
|
log.debug(curr.value + ' Table {');
|
||
|
tables[tableDefinitions[curr.value].tableName] = parseTable();
|
||
|
log.debug('}');
|
||
|
} else {
|
||
|
log.debug('Unhandled Table ' + curr.value);
|
||
|
}
|
||
|
} else {
|
||
|
// else ignored
|
||
|
curr = scanner.next();
|
||
|
}
|
||
|
}
|
||
|
|
||
|
curr = scanner.next();
|
||
|
return tables;
|
||
|
};
|
||
|
|
||
|
const END_OF_TABLE_VALUE = 'ENDTAB';
|
||
|
|
||
|
var parseTable = function() {
|
||
|
var tableDefinition = tableDefinitions[curr.value],
|
||
|
table = {},
|
||
|
expectedCount = 0,
|
||
|
actualCount;
|
||
|
|
||
|
curr = scanner.next();
|
||
|
while(!groupIs(0, END_OF_TABLE_VALUE)) {
|
||
|
|
||
|
switch(curr.code) {
|
||
|
case 5:
|
||
|
table.handle = curr.value;
|
||
|
curr = scanner.next();
|
||
|
break;
|
||
|
case 330:
|
||
|
table.ownerHandle = curr.value;
|
||
|
curr = scanner.next();
|
||
|
break;
|
||
|
case 100:
|
||
|
if(curr.value === 'AcDbSymbolTable') {
|
||
|
// ignore
|
||
|
curr = scanner.next();
|
||
|
}else{
|
||
|
logUnhandledGroup(curr);
|
||
|
curr = scanner.next();
|
||
|
}
|
||
|
break;
|
||
|
case 70:
|
||
|
expectedCount = curr.value;
|
||
|
curr = scanner.next();
|
||
|
break;
|
||
|
case 0:
|
||
|
if(curr.value === tableDefinition.dxfSymbolName) {
|
||
|
table[tableDefinition.tableRecordsProperty] = tableDefinition.parseTableRecords();
|
||
|
} else {
|
||
|
logUnhandledGroup(curr);
|
||
|
curr = scanner.next();
|
||
|
}
|
||
|
break;
|
||
|
default:
|
||
|
logUnhandledGroup(curr);
|
||
|
curr = scanner.next();
|
||
|
}
|
||
|
}
|
||
|
var tableRecords = table[tableDefinition.tableRecordsProperty];
|
||
|
if(tableRecords) {
|
||
|
if(tableRecords.constructor === Array){
|
||
|
actualCount = tableRecords.length;
|
||
|
} else if(typeof(tableRecords) === 'object') {
|
||
|
actualCount = Object.keys(tableRecords).length;
|
||
|
}
|
||
|
if(expectedCount !== actualCount) log.warn('Parsed ' + actualCount + ' ' + tableDefinition.dxfSymbolName + '\'s but expected ' + expectedCount);
|
||
|
}
|
||
|
curr = scanner.next();
|
||
|
return table;
|
||
|
};
|
||
|
|
||
|
var parseViewPortRecords = function() {
|
||
|
var viewPorts = [], // Multiple table entries may have the same name indicating a multiple viewport configuration
|
||
|
viewPort = {};
|
||
|
|
||
|
log.debug('ViewPort {');
|
||
|
curr = scanner.next();
|
||
|
while(!groupIs(0, END_OF_TABLE_VALUE)) {
|
||
|
|
||
|
switch(curr.code) {
|
||
|
case 2: // layer name
|
||
|
viewPort.name = curr.value;
|
||
|
curr = scanner.next();
|
||
|
break;
|
||
|
case 10:
|
||
|
viewPort.lowerLeftCorner = parsePoint();
|
||
|
curr = scanner.next();
|
||
|
break;
|
||
|
case 11:
|
||
|
viewPort.upperRightCorner = parsePoint();
|
||
|
curr = scanner.next();
|
||
|
break;
|
||
|
case 12:
|
||
|
viewPort.center = parsePoint();
|
||
|
curr = scanner.next();
|
||
|
break;
|
||
|
case 13:
|
||
|
viewPort.snapBasePoint = parsePoint();
|
||
|
curr = scanner.next();
|
||
|
break;
|
||
|
case 14:
|
||
|
viewPort.snapSpacing = parsePoint();
|
||
|
curr = scanner.next();
|
||
|
break;
|
||
|
case 15:
|
||
|
viewPort.gridSpacing = parsePoint();
|
||
|
curr = scanner.next();
|
||
|
break;
|
||
|
case 16:
|
||
|
viewPort.viewDirectionFromTarget = parsePoint();
|
||
|
curr = scanner.next();
|
||
|
break;
|
||
|
case 17:
|
||
|
viewPort.viewTarget = parsePoint();
|
||
|
curr = scanner.next();
|
||
|
break;
|
||
|
case 42:
|
||
|
viewPort.lensLength = curr.value;
|
||
|
curr = scanner.next();
|
||
|
break;
|
||
|
case 43:
|
||
|
viewPort.frontClippingPlane = curr.value;
|
||
|
curr = scanner.next();
|
||
|
break;
|
||
|
case 44:
|
||
|
viewPort.backClippingPlane = curr.value;
|
||
|
curr = scanner.next();
|
||
|
break;
|
||
|
case 45:
|
||
|
viewPort.viewHeight = curr.value;
|
||
|
curr = scanner.next();
|
||
|
break;
|
||
|
case 50:
|
||
|
viewPort.snapRotationAngle = curr.value;
|
||
|
curr = scanner.next();
|
||
|
break;
|
||
|
case 51:
|
||
|
viewPort.viewTwistAngle = curr.value;
|
||
|
curr = scanner.next();
|
||
|
break;
|
||
|
case 79:
|
||
|
viewPort.orthographicType = curr.value;
|
||
|
curr = scanner.next();
|
||
|
break;
|
||
|
case 110:
|
||
|
viewPort.ucsOrigin = parsePoint();
|
||
|
curr = scanner.next();
|
||
|
break;
|
||
|
case 111:
|
||
|
viewPort.ucsXAxis = parsePoint();
|
||
|
curr = scanner.next();
|
||
|
break;
|
||
|
case 112:
|
||
|
viewPort.ucsYAxis = parsePoint();
|
||
|
curr = scanner.next();
|
||
|
break;
|
||
|
case 110:
|
||
|
viewPort.ucsOrigin = parsePoint();
|
||
|
curr = scanner.next();
|
||
|
break;
|
||
|
case 281:
|
||
|
viewPort.renderMode = curr.value;
|
||
|
curr = scanner.next();
|
||
|
break;
|
||
|
case 281:
|
||
|
// 0 is one distant light, 1 is two distant lights
|
||
|
viewPort.defaultLightingType = curr.value;
|
||
|
curr = scanner.next();
|
||
|
break;
|
||
|
case 292:
|
||
|
viewPort.defaultLightingOn = curr.value;
|
||
|
curr = scanner.next();
|
||
|
break;
|
||
|
case 330:
|
||
|
viewPort.ownerHandle = curr.value;
|
||
|
curr = scanner.next();
|
||
|
break;
|
||
|
case 63:
|
||
|
case 421:
|
||
|
case 431:
|
||
|
viewPort.ambientColor = curr.value;
|
||
|
curr = scanner.next();
|
||
|
break;
|
||
|
case 0:
|
||
|
// New ViewPort
|
||
|
if(curr.value === 'VPORT') {
|
||
|
log.debug('}');
|
||
|
viewPorts.push(viewPort);
|
||
|
log.debug('ViewPort {');
|
||
|
viewPort = {};
|
||
|
curr = scanner.next();
|
||
|
}
|
||
|
break;
|
||
|
default:
|
||
|
logUnhandledGroup(curr);
|
||
|
curr = scanner.next();
|
||
|
break;
|
||
|
}
|
||
|
}
|
||
|
// Note: do not call scanner.next() here,
|
||
|
// parseTable() needs the current group
|
||
|
log.debug('}');
|
||
|
viewPorts.push(viewPort);
|
||
|
|
||
|
return viewPorts;
|
||
|
};
|
||
|
|
||
|
var parseLineTypes = function() {
|
||
|
var ltypes = {},
|
||
|
ltypeName,
|
||
|
ltype = {},
|
||
|
length;
|
||
|
|
||
|
log.debug('LType {');
|
||
|
curr = scanner.next();
|
||
|
while(!groupIs(0, 'ENDTAB')) {
|
||
|
|
||
|
switch(curr.code) {
|
||
|
case 2:
|
||
|
ltype.name = curr.value;
|
||
|
ltypeName = curr.value;
|
||
|
curr = scanner.next();
|
||
|
break;
|
||
|
case 3:
|
||
|
ltype.description = curr.value;
|
||
|
curr = scanner.next();
|
||
|
break;
|
||
|
case 73: // Number of elements for this line type (dots, dashes, spaces);
|
||
|
length = curr.value;
|
||
|
if(length > 0) ltype.pattern = [];
|
||
|
curr = scanner.next();
|
||
|
break;
|
||
|
case 40: // total pattern length
|
||
|
ltype.patternLength = curr.value;
|
||
|
curr = scanner.next();
|
||
|
break;
|
||
|
case 49:
|
||
|
ltype.pattern.push(curr.value);
|
||
|
curr = scanner.next();
|
||
|
break;
|
||
|
case 0:
|
||
|
log.debug('}');
|
||
|
if(length > 0 && length !== ltype.pattern.length) log.warn('lengths do not match on LTYPE pattern');
|
||
|
ltypes[ltypeName] = ltype;
|
||
|
ltype = {};
|
||
|
log.debug('LType {');
|
||
|
curr = scanner.next();
|
||
|
break;
|
||
|
default:
|
||
|
curr = scanner.next();
|
||
|
}
|
||
|
}
|
||
|
|
||
|
log.debug('}');
|
||
|
ltypes[ltypeName] = ltype;
|
||
|
return ltypes;
|
||
|
};
|
||
|
|
||
|
var parseLayers = function() {
|
||
|
var layers = {},
|
||
|
layerName,
|
||
|
layer = {};
|
||
|
|
||
|
log.debug('Layer {');
|
||
|
curr = scanner.next();
|
||
|
while(!groupIs(0, 'ENDTAB')) {
|
||
|
|
||
|
switch(curr.code) {
|
||
|
case 2: // layer name
|
||
|
layer.name = curr.value;
|
||
|
layerName = curr.value;
|
||
|
curr = scanner.next();
|
||
|
break;
|
||
|
case 62: // color, visibility
|
||
|
layer.visible = curr.value >= 0;
|
||
|
// TODO 0 and 256 are BYBLOCK and BYLAYER respectively. Need to handle these values for layers?.
|
||
|
layer.color = getAcadColor(Math.abs(curr.value));
|
||
|
curr = scanner.next();
|
||
|
break;
|
||
|
case 70: // frozen layer
|
||
|
layer.frozen = ((curr.value & 1) != 0 || (curr.value & 2) != 0);
|
||
|
curr = scanner.next();
|
||
|
break;
|
||
|
case 0:
|
||
|
// New Layer
|
||
|
if(curr.value === 'LAYER') {
|
||
|
log.debug('}');
|
||
|
layers[layerName] = layer;
|
||
|
log.debug('Layer {');
|
||
|
layer = {};
|
||
|
layerName = undefined;
|
||
|
curr = scanner.next();
|
||
|
}
|
||
|
break;
|
||
|
default:
|
||
|
logUnhandledGroup(curr);
|
||
|
curr = scanner.next();
|
||
|
break;
|
||
|
}
|
||
|
}
|
||
|
// Note: do not call scanner.next() here,
|
||
|
// parseLayerTable() needs the current group
|
||
|
log.debug('}');
|
||
|
layers[layerName] = layer;
|
||
|
|
||
|
return layers;
|
||
|
};
|
||
|
|
||
|
var tableDefinitions = {
|
||
|
VPORT: {
|
||
|
tableRecordsProperty: 'viewPorts',
|
||
|
tableName: 'viewPort',
|
||
|
dxfSymbolName: 'VPORT',
|
||
|
parseTableRecords: parseViewPortRecords
|
||
|
},
|
||
|
LTYPE: {
|
||
|
tableRecordsProperty: 'lineTypes',
|
||
|
tableName: 'lineType',
|
||
|
dxfSymbolName: 'LTYPE',
|
||
|
parseTableRecords: parseLineTypes
|
||
|
},
|
||
|
LAYER: {
|
||
|
tableRecordsProperty: 'layers',
|
||
|
tableName: 'layer',
|
||
|
dxfSymbolName: 'LAYER',
|
||
|
parseTableRecords: parseLayers
|
||
|
}
|
||
|
};
|
||
|
|
||
|
/**
|
||
|
* Is called after the parser first reads the 0:ENTITIES group. The scanner
|
||
|
* should be on the start of the first entity already.
|
||
|
* @return {Array} the resulting entities
|
||
|
*/
|
||
|
var parseEntities = function(forBlock) {
|
||
|
var entities = [];
|
||
|
|
||
|
var endingOnValue = forBlock ? 'ENDBLK' : 'ENDSEC';
|
||
|
|
||
|
if (!forBlock) {
|
||
|
curr = scanner.next();
|
||
|
}
|
||
|
while(true) {
|
||
|
|
||
|
if(curr.code === 0) {
|
||
|
if(curr.value === endingOnValue) {
|
||
|
break;
|
||
|
}
|
||
|
|
||
|
var entity;
|
||
|
var handler = self._entityHandlers[curr.value];
|
||
|
if(handler != null) {
|
||
|
log.debug(curr.value + ' {');
|
||
|
entity = handler.parseEntity(scanner, curr);
|
||
|
curr = scanner.lastReadGroup;
|
||
|
log.debug('}');
|
||
|
} else {
|
||
|
log.warn('Unhandled entity ' + curr.value);
|
||
|
curr = scanner.next();
|
||
|
continue;
|
||
|
}
|
||
|
ensureHandle(entity);
|
||
|
entities.push(entity);
|
||
|
} else {
|
||
|
// ignored lines from unsupported entity
|
||
|
curr = scanner.next();
|
||
|
}
|
||
|
}
|
||
|
if(endingOnValue == 'ENDSEC') curr = scanner.next(); // swallow up ENDSEC, but not ENDBLK
|
||
|
return entities;
|
||
|
};
|
||
|
|
||
|
/**
|
||
|
* Parses a 2D or 3D point, returning it as an object with x, y, and
|
||
|
* (sometimes) z property if it is 3D. It is assumed the current group
|
||
|
* is x of the point being read in, and scanner.next() will return the
|
||
|
* y. The parser will determine if there is a z point automatically.
|
||
|
* @return {Object} The 2D or 3D point as an object with x, y[, z]
|
||
|
*/
|
||
|
var parsePoint = function() {
|
||
|
var point = {},
|
||
|
code = curr.code;
|
||
|
|
||
|
point.x = curr.value;
|
||
|
|
||
|
code += 10;
|
||
|
curr = scanner.next();
|
||
|
if(curr.code != code)
|
||
|
throw new Error('Expected code for point value to be ' + code +
|
||
|
' but got ' + curr.code + '.');
|
||
|
point.y = curr.value;
|
||
|
|
||
|
code += 10;
|
||
|
curr = scanner.next();
|
||
|
if(curr.code != code)
|
||
|
{
|
||
|
scanner.rewind();
|
||
|
return point;
|
||
|
}
|
||
|
point.z = curr.value;
|
||
|
|
||
|
return point;
|
||
|
};
|
||
|
|
||
|
var ensureHandle = function(entity) {
|
||
|
if(!entity) throw new TypeError('entity cannot be undefined or null');
|
||
|
|
||
|
if(!entity.handle) entity.handle = lastHandle++;
|
||
|
};
|
||
|
|
||
|
parseAll();
|
||
|
return dxf;
|
||
|
};
|
||
|
|
||
|
function logUnhandledGroup(curr) {
|
||
|
log.debug('unhandled group ' + debugCode(curr));
|
||
|
}
|
||
|
|
||
|
|
||
|
function debugCode(curr) {
|
||
|
return curr.code + ':' + curr.value;
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Returns the truecolor value of the given AutoCad color index value
|
||
|
* @return {Number} truecolor value as a number
|
||
|
*/
|
||
|
function getAcadColor(index) {
|
||
|
return AUTO_CAD_COLOR_INDEX[index];
|
||
|
}
|
||
|
|
||
|
const BLOCK_ANONYMOUS_FLAG = 1;
|
||
|
const BLOCK_NON_CONSTANT_FLAG = 2;
|
||
|
const BLOCK_XREF_FLAG = 4;
|
||
|
const BLOCK_XREF_OVERLAY_FLAG = 8;
|
||
|
const BLOCK_EXTERNALLY_DEPENDENT_FLAG = 16;
|
||
|
const BLOCK_RESOLVED_OR_DEPENDENT_FLAG = 32;
|
||
|
const BLOCK_REFERENCED_XREF = 64;
|
||
|
|
||
|
|
||
|
|
||
|
module.exports = DxfParser;
|
||
|
|
||
|
|
||
|
/* Notes */
|
||
|
// Code 6 of an entity indicates inheritance of properties (eg. color).
|
||
|
// BYBLOCK means inherits from block
|
||
|
// BYLAYER (default) mean inherits from layer
|
||
|
},{"./AutoCadColorIndex":1,"./DxfArrayScanner.js":2,"./entities/3dface":5,"./entities/arc":6,"./entities/attdef":7,"./entities/circle":8,"./entities/dimension":9,"./entities/ellipse":10,"./entities/insert":11,"./entities/line":12,"./entities/lwpolyline":13,"./entities/mtext":14,"./entities/point":15,"./entities/polyline":16,"./entities/solid":17,"./entities/spline":18,"./entities/text":19,"loglevel":21}],4:[function(require,module,exports){
|
||
|
var AUTO_CAD_COLOR_INDEX = require('./AutoCadColorIndex');
|
||
|
|
||
|
/**
|
||
|
* Returns the truecolor value of the given AutoCad color index value
|
||
|
* @return {Number} truecolor value as a number
|
||
|
*/
|
||
|
exports.getAcadColor = function(index) {
|
||
|
return AUTO_CAD_COLOR_INDEX[index];
|
||
|
}
|
||
|
var getAcadColor = exports.getAcadColor;
|
||
|
|
||
|
/**
|
||
|
* Parses the 2D or 3D coordinate, vector, or point. When complete,
|
||
|
* the scanner remains on the last group of the coordinate.
|
||
|
* @param {*} scanner
|
||
|
*/
|
||
|
exports.parsePoint = function(scanner) {
|
||
|
var point = {};
|
||
|
|
||
|
// Reread group for the first coordinate
|
||
|
scanner.rewind();
|
||
|
var curr = scanner.next();
|
||
|
|
||
|
code = curr.code;
|
||
|
point.x = curr.value;
|
||
|
|
||
|
code += 10;
|
||
|
curr = scanner.next();
|
||
|
if(curr.code != code)
|
||
|
throw new Error('Expected code for point value to be ' + code +
|
||
|
' but got ' + curr.code + '.');
|
||
|
point.y = curr.value;
|
||
|
|
||
|
code += 10;
|
||
|
curr = scanner.next();
|
||
|
if(curr.code != code)
|
||
|
{
|
||
|
// Only the x and y are specified. Don't read z.
|
||
|
scanner.rewind(); // Let the calling code advance off the point
|
||
|
return point;
|
||
|
}
|
||
|
point.z = curr.value;
|
||
|
|
||
|
return point;
|
||
|
};
|
||
|
|
||
|
/**
|
||
|
* Attempts to parse codes common to all entities. Returns true if the group
|
||
|
* was handled by this function.
|
||
|
* @param {*} entity - the entity currently being parsed
|
||
|
* @param {*} curr - the current group being parsed
|
||
|
*/
|
||
|
exports.checkCommonEntityProperties = function(entity, curr) {
|
||
|
switch(curr.code) {
|
||
|
case 0:
|
||
|
entity.type = curr.value;
|
||
|
break;
|
||
|
case 5:
|
||
|
entity.handle = curr.value;
|
||
|
break;
|
||
|
case 6:
|
||
|
entity.lineType = curr.value;
|
||
|
break;
|
||
|
case 8: // Layer name
|
||
|
entity.layer = curr.value;
|
||
|
break;
|
||
|
case 48:
|
||
|
entity.lineTypeScale = curr.value;
|
||
|
break;
|
||
|
case 60:
|
||
|
entity.visible = curr.value === 0;
|
||
|
break;
|
||
|
case 62: // Acad Index Color. 0 inherits ByBlock. 256 inherits ByLayer. Default is bylayer
|
||
|
entity.colorIndex = curr.value;
|
||
|
entity.color = getAcadColor(Math.abs(curr.value));
|
||
|
break;
|
||
|
case 67:
|
||
|
entity.inPaperSpace = curr.value !== 0;
|
||
|
break;
|
||
|
case 100:
|
||
|
//ignore
|
||
|
break;
|
||
|
case 330:
|
||
|
entity.ownerHandle = curr.value;
|
||
|
break;
|
||
|
case 347:
|
||
|
entity.materialObjectHandle = curr.value;
|
||
|
break;
|
||
|
case 370:
|
||
|
//From https://www.woutware.com/Forum/Topic/955/lineweight?returnUrl=%2FForum%2FUserPosts%3FuserId%3D478262319
|
||
|
// An integer representing 100th of mm, must be one of the following values:
|
||
|
// 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 = STANDARD, -2 = BYLAYER, -1 = BYBLOCK
|
||
|
entity.lineweight = curr.value;
|
||
|
break;
|
||
|
case 420: // TrueColor Color
|
||
|
entity.color = curr.value;
|
||
|
break;
|
||
|
case 1000:
|
||
|
entity.extendedData = entity.extendedData || {};
|
||
|
entity.extendedData.customStrings = entity.extendedData.customStrings || [];
|
||
|
entity.extendedData.customStrings.push(curr.value);
|
||
|
break;
|
||
|
case 1001:
|
||
|
entity.extendedData = entity.extendedData || {};
|
||
|
entity.extendedData.applicationName = curr.value;
|
||
|
break;
|
||
|
default:
|
||
|
return false;
|
||
|
}
|
||
|
return true;
|
||
|
};
|
||
|
|
||
|
},{"./AutoCadColorIndex":1}],5:[function(require,module,exports){
|
||
|
|
||
|
var helpers = require('../ParseHelpers');
|
||
|
|
||
|
module.exports = EntityParser;
|
||
|
|
||
|
function EntityParser() {}
|
||
|
|
||
|
EntityParser.ForEntityName = '3DFACE';
|
||
|
|
||
|
EntityParser.prototype.parseEntity = function(scanner, curr) {
|
||
|
|
||
|
var entity = { type: curr.value, vertices: [] };
|
||
|
curr = scanner.next();
|
||
|
while (curr !== 'EOF') {
|
||
|
if (curr.code === 0) break;
|
||
|
switch (curr.code) {
|
||
|
case 70: // 1 = Closed shape, 128 = plinegen?, 0 = default
|
||
|
entity.shape = ((curr.value & 1) === 1);
|
||
|
entity.hasContinuousLinetypePattern = ((curr.value & 128) === 128);
|
||
|
break;
|
||
|
case 10: // X coordinate of point
|
||
|
entity.vertices = parse3dFaceVertices(scanner, curr);
|
||
|
curr = scanner.lastReadGroup;
|
||
|
break;
|
||
|
default:
|
||
|
checkCommonEntityProperties(entity);
|
||
|
break;
|
||
|
}
|
||
|
curr = scanner.next();
|
||
|
}
|
||
|
return entity;
|
||
|
};
|
||
|
|
||
|
function parse3dFaceVertices(scanner, curr) {
|
||
|
var vertices = [],
|
||
|
i;
|
||
|
var vertexIsStarted = false;
|
||
|
var vertexIsFinished = false;
|
||
|
var verticesPer3dFace = 4; // there can be up to four vertices per face, although 3 is most used for TIN
|
||
|
|
||
|
for (i = 0; i <= verticesPer3dFace; i++) {
|
||
|
var vertex = {};
|
||
|
while (curr !== 'EOF') {
|
||
|
if (curr.code === 0 || vertexIsFinished) break;
|
||
|
|
||
|
switch (curr.code) {
|
||
|
case 10: // X0
|
||
|
case 11: // X1
|
||
|
case 12: // X2
|
||
|
case 13: // X3
|
||
|
if (vertexIsStarted) {
|
||
|
vertexIsFinished = true;
|
||
|
continue;
|
||
|
}
|
||
|
vertex.x = curr.value;
|
||
|
vertexIsStarted = true;
|
||
|
break;
|
||
|
case 20: // Y
|
||
|
case 21:
|
||
|
case 22:
|
||
|
case 23:
|
||
|
vertex.y = curr.value;
|
||
|
break;
|
||
|
case 30: // Z
|
||
|
case 31:
|
||
|
case 32:
|
||
|
case 33:
|
||
|
vertex.z = curr.value;
|
||
|
break;
|
||
|
default:
|
||
|
// it is possible to have entity codes after the vertices.
|
||
|
// So if code is not accounted for return to entity parser where it might be accounted for
|
||
|
return vertices;
|
||
|
continue;
|
||
|
}
|
||
|
curr = scanner.next();
|
||
|
}
|
||
|
// See https://groups.google.com/forum/#!topic/comp.cad.autocad/9gn8s5O_w6E
|
||
|
vertices.push(vertex);
|
||
|
vertexIsStarted = false;
|
||
|
vertexIsFinished = false;
|
||
|
}
|
||
|
scanner.rewind();
|
||
|
return vertices;
|
||
|
};
|
||
|
},{"../ParseHelpers":4}],6:[function(require,module,exports){
|
||
|
|
||
|
var helpers = require('../ParseHelpers');
|
||
|
|
||
|
module.exports = EntityParser;
|
||
|
|
||
|
function EntityParser() {}
|
||
|
|
||
|
EntityParser.ForEntityName = 'ARC';
|
||
|
|
||
|
EntityParser.prototype.parseEntity = function(scanner, curr) {
|
||
|
var entity, endAngle;
|
||
|
entity = { type: curr.value };
|
||
|
curr = scanner.next();
|
||
|
while(curr !== 'EOF') {
|
||
|
if(curr.code === 0) break;
|
||
|
|
||
|
switch(curr.code) {
|
||
|
case 10: // X coordinate of point
|
||
|
entity.center = helpers.parsePoint(scanner);
|
||
|
break;
|
||
|
case 40: // radius
|
||
|
entity.radius = curr.value;
|
||
|
break;
|
||
|
case 50: // start angle
|
||
|
entity.startAngle = Math.PI / 180 * curr.value;
|
||
|
break;
|
||
|
case 51: // end angle
|
||
|
entity.endAngle = Math.PI / 180 * curr.value;
|
||
|
entity.angleLength = entity.endAngle - entity.startAngle; // angleLength is deprecated
|
||
|
break;
|
||
|
default: // ignored attribute
|
||
|
helpers.checkCommonEntityProperties(entity, curr);
|
||
|
break;
|
||
|
}
|
||
|
curr = scanner.next();
|
||
|
}
|
||
|
return entity;
|
||
|
};
|
||
|
},{"../ParseHelpers":4}],7:[function(require,module,exports){
|
||
|
|
||
|
var helpers = require('../ParseHelpers');
|
||
|
|
||
|
module.exports = EntityParser;
|
||
|
|
||
|
function EntityParser() {}
|
||
|
|
||
|
EntityParser.ForEntityName = 'ATTDEF';
|
||
|
|
||
|
EntityParser.prototype.parseEntity = function(scanner, curr) {
|
||
|
var entity = {
|
||
|
type: curr.value,
|
||
|
scale: 1,
|
||
|
textStyle: 'STANDARD'
|
||
|
};
|
||
|
curr = scanner.next();
|
||
|
while (curr !== 'EOF') {
|
||
|
if (curr.code === 0) {
|
||
|
break;
|
||
|
}
|
||
|
switch(curr.code) {
|
||
|
case 1:
|
||
|
entity.text = curr.value;
|
||
|
break;
|
||
|
case 2:
|
||
|
entity.tag = curr.value;
|
||
|
break;
|
||
|
case 3:
|
||
|
entity.prompt = curr.value;
|
||
|
break;
|
||
|
case 7:
|
||
|
entity.textStyle = curr.value;
|
||
|
break;
|
||
|
case 10: // X coordinate of 'first alignment point'
|
||
|
entity.startPoint = helpers.parsePoint(scanner);
|
||
|
break;
|
||
|
case 11: // X coordinate of 'second alignment point'
|
||
|
entity.endPoint = helpers.parsePoint(scanner);
|
||
|
break;
|
||
|
case 39:
|
||
|
entity.thickness = curr.value;
|
||
|
break;
|
||
|
case 40:
|
||
|
entity.textHeight = curr.value;
|
||
|
break;
|
||
|
case 41:
|
||
|
entity.scale = curr.value;
|
||
|
break;
|
||
|
case 50:
|
||
|
entity.rotation = curr.value;
|
||
|
break;
|
||
|
case 51:
|
||
|
entity.obliqueAngle = curr.value;
|
||
|
break;
|
||
|
case 70:
|
||
|
entity.invisible = !!(curr.value & 0x01);
|
||
|
entity.constant = !!(curr.value & 0x02);
|
||
|
entity.verificationRequired = !!(curr.value & 0x04);
|
||
|
entity.preset = !!(curr.value & 0x08);
|
||
|
break;
|
||
|
case 71:
|
||
|
entity.backwards = !!(curr.value & 0x02);
|
||
|
entity.mirrored = !!(curr.value & 0x04);
|
||
|
break;
|
||
|
case 72:
|
||
|
// TODO: enum values?
|
||
|
entity.horizontalJustification = curr.value;
|
||
|
break;
|
||
|
case 73:
|
||
|
entity.fieldLength = curr.value;
|
||
|
break;
|
||
|
case 74:
|
||
|
// TODO: enum values?
|
||
|
entity.verticalJustification = curr.value;
|
||
|
break;
|
||
|
case 100:
|
||
|
break;
|
||
|
case 210:
|
||
|
entity.extrusionDirectionX = curr.value;
|
||
|
break;
|
||
|
case 220:
|
||
|
entity.extrusionDirectionY = curr.value;
|
||
|
break;
|
||
|
case 230:
|
||
|
entity.extrusionDirectionZ = curr.value;
|
||
|
break;
|
||
|
default:
|
||
|
helpers.checkCommonEntityProperties(entity, curr);
|
||
|
break;
|
||
|
}
|
||
|
curr = scanner.next();
|
||
|
}
|
||
|
|
||
|
return entity;
|
||
|
};
|
||
|
},{"../ParseHelpers":4}],8:[function(require,module,exports){
|
||
|
|
||
|
var helpers = require('../ParseHelpers');
|
||
|
|
||
|
module.exports = EntityParser;
|
||
|
|
||
|
function EntityParser() {}
|
||
|
|
||
|
EntityParser.ForEntityName = 'CIRCLE';
|
||
|
|
||
|
EntityParser.prototype.parseEntity = function(scanner, curr) {
|
||
|
var entity, endAngle;
|
||
|
entity = { type: curr.value };
|
||
|
curr = scanner.next();
|
||
|
while(curr !== 'EOF') {
|
||
|
if(curr.code === 0) break;
|
||
|
|
||
|
switch(curr.code) {
|
||
|
case 10: // X coordinate of point
|
||
|
entity.center = helpers.parsePoint(scanner);
|
||
|
break;
|
||
|
case 40: // radius
|
||
|
entity.radius = curr.value;
|
||
|
break;
|
||
|
case 50: // start angle
|
||
|
entity.startAngle = Math.PI / 180 * curr.value;
|
||
|
break;
|
||
|
case 51: // end angle
|
||
|
endAngle = Math.PI / 180 * curr.value;
|
||
|
if(endAngle < entity.startAngle)
|
||
|
entity.angleLength = endAngle + 2 * Math.PI - entity.startAngle;
|
||
|
else
|
||
|
entity.angleLength = endAngle - entity.startAngle;
|
||
|
entity.endAngle = endAngle;
|
||
|
break;
|
||
|
default: // ignored attribute
|
||
|
helpers.checkCommonEntityProperties(entity, curr);
|
||
|
break;
|
||
|
}
|
||
|
curr = scanner.next();
|
||
|
}
|
||
|
return entity;
|
||
|
};
|
||
|
},{"../ParseHelpers":4}],9:[function(require,module,exports){
|
||
|
|
||
|
var helpers = require('../ParseHelpers');
|
||
|
|
||
|
module.exports = EntityParser;
|
||
|
|
||
|
function EntityParser() {}
|
||
|
|
||
|
EntityParser.ForEntityName = 'DIMENSION';
|
||
|
|
||
|
EntityParser.prototype.parseEntity = function(scanner, curr) {
|
||
|
var entity;
|
||
|
entity = { type: curr.value };
|
||
|
curr = scanner.next();
|
||
|
while(curr !== 'EOF') {
|
||
|
if(curr.code === 0) break;
|
||
|
|
||
|
switch(curr.code) {
|
||
|
case 2: // Referenced block name
|
||
|
entity.block = curr.value;
|
||
|
break;
|
||
|
case 10: // X coordinate of 'first alignment point'
|
||
|
entity.anchorPoint = helpers.parsePoint(scanner);
|
||
|
break;
|
||
|
case 11:
|
||
|
entity.middleOfText = helpers.parsePoint(scanner);
|
||
|
break;
|
||
|
case 71: // 5 = Middle center
|
||
|
entity.attachmentPoint = curr.value;
|
||
|
break;
|
||
|
case 42: // Actual measurement
|
||
|
entity.actualMeasurement = curr.value;
|
||
|
break;
|
||
|
case 1: // Text entered by user explicitly
|
||
|
entity.text = curr.value;
|
||
|
break;
|
||
|
case 50: // Angle of rotated, horizontal, or vertical dimensions
|
||
|
entity.angle = curr.value;
|
||
|
break;
|
||
|
default: // check common entity attributes
|
||
|
helpers.checkCommonEntityProperties(entity, curr);
|
||
|
break;
|
||
|
}
|
||
|
curr = scanner.next();
|
||
|
}
|
||
|
|
||
|
return entity;
|
||
|
};
|
||
|
|
||
|
|
||
|
|
||
|
},{"../ParseHelpers":4}],10:[function(require,module,exports){
|
||
|
|
||
|
var helpers = require('../ParseHelpers');
|
||
|
|
||
|
module.exports = EntityParser;
|
||
|
|
||
|
function EntityParser() {}
|
||
|
|
||
|
EntityParser.ForEntityName = 'ELLIPSE';
|
||
|
|
||
|
EntityParser.prototype.parseEntity = function(scanner, curr) {
|
||
|
var entity;
|
||
|
entity = { type: curr.value };
|
||
|
curr = scanner.next();
|
||
|
while(curr !== 'EOF') {
|
||
|
if(curr.code === 0) break;
|
||
|
|
||
|
switch(curr.code) {
|
||
|
case 10:
|
||
|
entity.center = helpers.parsePoint(scanner);
|
||
|
break;
|
||
|
case 11:
|
||
|
entity.majorAxisEndPoint = helpers.parsePoint(scanner);
|
||
|
break;
|
||
|
case 40:
|
||
|
entity.axisRatio = curr.value;
|
||
|
break;
|
||
|
case 41:
|
||
|
entity.startAngle = curr.value;
|
||
|
break;
|
||
|
case 42:
|
||
|
entity.endAngle = curr.value;
|
||
|
break;
|
||
|
case 2:
|
||
|
entity.name = curr.value;
|
||
|
break;
|
||
|
default: // check common entity attributes
|
||
|
helpers.checkCommonEntityProperties(entity, curr);
|
||
|
break;
|
||
|
}
|
||
|
|
||
|
curr = scanner.next();
|
||
|
}
|
||
|
|
||
|
return entity;
|
||
|
};
|
||
|
},{"../ParseHelpers":4}],11:[function(require,module,exports){
|
||
|
|
||
|
var helpers = require('../ParseHelpers');
|
||
|
|
||
|
module.exports = EntityParser;
|
||
|
|
||
|
function EntityParser() {}
|
||
|
|
||
|
EntityParser.ForEntityName = 'INSERT';
|
||
|
|
||
|
EntityParser.prototype.parseEntity = function(scanner, curr) {
|
||
|
var entity;
|
||
|
entity = { type: curr.value };
|
||
|
curr = scanner.next();
|
||
|
while(curr !== 'EOF') {
|
||
|
if(curr.code === 0) break;
|
||
|
|
||
|
switch(curr.code) {
|
||
|
case 2:
|
||
|
entity.name = curr.value;
|
||
|
break;
|
||
|
case 41:
|
||
|
entity.xScale = curr.value;
|
||
|
break;
|
||
|
case 42:
|
||
|
entity.yScale = curr.value;
|
||
|
break;
|
||
|
case 43:
|
||
|
entity.zScale = curr.value;
|
||
|
break;
|
||
|
case 10:
|
||
|
entity.position = helpers.parsePoint(scanner);
|
||
|
break;
|
||
|
case 50:
|
||
|
entity.rotation = curr.value;
|
||
|
break;
|
||
|
case 70:
|
||
|
entity.columnCount = curr.value;
|
||
|
break;
|
||
|
case 71:
|
||
|
entity.rowCount = curr.value;
|
||
|
break;
|
||
|
case 44:
|
||
|
entity.columnSpacing = curr.value;
|
||
|
break;
|
||
|
case 45:
|
||
|
entity.rowSpacing = curr.value;
|
||
|
break;
|
||
|
case 210:
|
||
|
entity.extrusionDirection = helpers.parsePoint(scanner);
|
||
|
break;
|
||
|
default: // check common entity attributes
|
||
|
helpers.checkCommonEntityProperties(entity, curr);
|
||
|
break;
|
||
|
}
|
||
|
curr = scanner.next();
|
||
|
}
|
||
|
|
||
|
return entity;
|
||
|
};
|
||
|
|
||
|
|
||
|
|
||
|
},{"../ParseHelpers":4}],12:[function(require,module,exports){
|
||
|
|
||
|
var helpers = require('../ParseHelpers');
|
||
|
|
||
|
module.exports = EntityParser;
|
||
|
|
||
|
function EntityParser() {}
|
||
|
|
||
|
EntityParser.ForEntityName = 'LINE';
|
||
|
|
||
|
EntityParser.prototype.parseEntity = function(scanner, curr) {
|
||
|
var entity = { type: curr.value, vertices: [] };
|
||
|
curr = scanner.next();
|
||
|
while(curr !== 'EOF') {
|
||
|
if(curr.code === 0) break;
|
||
|
|
||
|
switch(curr.code) {
|
||
|
case 10: // X coordinate of point
|
||
|
entity.vertices.unshift(helpers.parsePoint(scanner));
|
||
|
break;
|
||
|
case 11:
|
||
|
entity.vertices.push(helpers.parsePoint(scanner));
|
||
|
break;
|
||
|
case 210:
|
||
|
entity.extrusionDirection = helpers.parsePoint(scanner);
|
||
|
break;
|
||
|
case 100:
|
||
|
break;
|
||
|
default:
|
||
|
helpers.checkCommonEntityProperties(entity, curr);
|
||
|
break;
|
||
|
}
|
||
|
|
||
|
curr = scanner.next();
|
||
|
}
|
||
|
return entity;
|
||
|
};
|
||
|
},{"../ParseHelpers":4}],13:[function(require,module,exports){
|
||
|
|
||
|
var helpers = require('../ParseHelpers');
|
||
|
|
||
|
module.exports = EntityParser;
|
||
|
|
||
|
function EntityParser() {}
|
||
|
|
||
|
EntityParser.ForEntityName = 'LWPOLYLINE';
|
||
|
|
||
|
EntityParser.prototype.parseEntity = function(scanner, curr) {
|
||
|
var entity = { type: curr.value, vertices: [] },
|
||
|
numberOfVertices = 0;
|
||
|
curr = scanner.next();
|
||
|
while(curr !== 'EOF') {
|
||
|
if(curr.code === 0) break;
|
||
|
|
||
|
switch(curr.code) {
|
||
|
case 38:
|
||
|
entity.elevation = curr.value;
|
||
|
break;
|
||
|
case 39:
|
||
|
entity.depth = curr.value;
|
||
|
break;
|
||
|
case 70: // 1 = Closed shape, 128 = plinegen?, 0 = default
|
||
|
entity.shape = ((curr.value & 1) === 1);
|
||
|
entity.hasContinuousLinetypePattern = ((curr.value & 128) === 128);
|
||
|
break;
|
||
|
case 90:
|
||
|
numberOfVertices = curr.value;
|
||
|
break;
|
||
|
case 10: // X coordinate of point
|
||
|
entity.vertices = parseLWPolylineVertices(numberOfVertices, scanner);
|
||
|
break;
|
||
|
case 43:
|
||
|
if(curr.value !== 0) entity.width = curr.value;
|
||
|
break;
|
||
|
case 210:
|
||
|
entity.extrusionDirectionX = curr.value;
|
||
|
break;
|
||
|
case 220:
|
||
|
entity.extrusionDirectionY = curr.value;
|
||
|
break;
|
||
|
case 230:
|
||
|
entity.extrusionDirectionZ = curr.value;
|
||
|
break;
|
||
|
default:
|
||
|
helpers.checkCommonEntityProperties(entity, curr);
|
||
|
break;
|
||
|
}
|
||
|
curr = scanner.next();
|
||
|
}
|
||
|
return entity;
|
||
|
};
|
||
|
|
||
|
function parseLWPolylineVertices(n, scanner) {
|
||
|
if(!n || n <= 0) throw Error('n must be greater than 0 verticies');
|
||
|
var vertices = [], i;
|
||
|
var vertexIsStarted = false;
|
||
|
var vertexIsFinished = false;
|
||
|
var curr = scanner.lastReadGroup;
|
||
|
|
||
|
for(i = 0; i < n; i++) {
|
||
|
var vertex = {};
|
||
|
while(curr !== 'EOF') {
|
||
|
if(curr.code === 0 || vertexIsFinished) break;
|
||
|
|
||
|
switch(curr.code) {
|
||
|
case 10: // X
|
||
|
if(vertexIsStarted) {
|
||
|
vertexIsFinished = true;
|
||
|
continue;
|
||
|
}
|
||
|
vertex.x = curr.value;
|
||
|
vertexIsStarted = true;
|
||
|
break;
|
||
|
case 20: // Y
|
||
|
vertex.y = curr.value;
|
||
|
break;
|
||
|
case 30: // Z
|
||
|
vertex.z = curr.value;
|
||
|
break;
|
||
|
case 40: // start width
|
||
|
vertex.startWidth = curr.value;
|
||
|
break;
|
||
|
case 41: // end width
|
||
|
vertex.endWidth = curr.value;
|
||
|
break;
|
||
|
case 42: // bulge
|
||
|
if(curr.value != 0) vertex.bulge = curr.value;
|
||
|
break;
|
||
|
default:
|
||
|
// if we do not hit known code return vertices. Code might belong to entity
|
||
|
if (vertexIsStarted) {
|
||
|
vertices.push(vertex);
|
||
|
}
|
||
|
return vertices;
|
||
|
}
|
||
|
curr = scanner.next();
|
||
|
}
|
||
|
// See https://groups.google.com/forum/#!topic/comp.cad.autocad/9gn8s5O_w6E
|
||
|
vertices.push(vertex);
|
||
|
vertexIsStarted = false;
|
||
|
vertexIsFinished = false;
|
||
|
}
|
||
|
scanner.rewind();
|
||
|
return vertices;
|
||
|
};
|
||
|
},{"../ParseHelpers":4}],14:[function(require,module,exports){
|
||
|
|
||
|
var helpers = require('../ParseHelpers');
|
||
|
|
||
|
module.exports = EntityParser;
|
||
|
|
||
|
function EntityParser() {}
|
||
|
|
||
|
EntityParser.ForEntityName = 'MTEXT';
|
||
|
|
||
|
EntityParser.prototype.parseEntity = function(scanner, curr) {
|
||
|
var entity = { type: curr.value };
|
||
|
curr = scanner.next();
|
||
|
while(curr !== 'EOF') {
|
||
|
if(curr.code === 0) break;
|
||
|
|
||
|
switch(curr.code) {
|
||
|
case 1:
|
||
|
entity.text = curr.value;
|
||
|
break;
|
||
|
case 3:
|
||
|
entity.text += curr.value;
|
||
|
break;
|
||
|
case 10:
|
||
|
entity.position = helpers.parsePoint(scanner);
|
||
|
break;
|
||
|
case 40:
|
||
|
//Note: this is the text height
|
||
|
entity.height = curr.value;
|
||
|
break;
|
||
|
case 41:
|
||
|
entity.width = curr.value;
|
||
|
break;
|
||
|
case 50:
|
||
|
entity.rotation = curr.value;
|
||
|
break;
|
||
|
case 71:
|
||
|
entity.attachmentPoint = curr.value;
|
||
|
break;
|
||
|
case 72:
|
||
|
entity.drawingDirection = curr.value;
|
||
|
break;
|
||
|
default:
|
||
|
helpers.checkCommonEntityProperties(entity, curr);
|
||
|
break;
|
||
|
}
|
||
|
curr = scanner.next();
|
||
|
}
|
||
|
return entity;
|
||
|
};
|
||
|
},{"../ParseHelpers":4}],15:[function(require,module,exports){
|
||
|
|
||
|
var helpers = require('../ParseHelpers');
|
||
|
|
||
|
module.exports = EntityParser;
|
||
|
|
||
|
function EntityParser() {}
|
||
|
|
||
|
EntityParser.ForEntityName = 'POINT';
|
||
|
|
||
|
EntityParser.prototype.parseEntity = function(scanner, curr) {
|
||
|
var entity;
|
||
|
entity = { type: curr.value };
|
||
|
curr = scanner.next();
|
||
|
while(curr !== 'EOF') {
|
||
|
if(curr.code === 0) break;
|
||
|
|
||
|
switch(curr.code) {
|
||
|
case 10:
|
||
|
entity.position = helpers.parsePoint(scanner);
|
||
|
break;
|
||
|
case 39:
|
||
|
entity.thickness = curr.value;
|
||
|
break;
|
||
|
case 210:
|
||
|
entity.extrusionDirection = helpers.parsePoint(scanner);
|
||
|
break;
|
||
|
case 100:
|
||
|
break;
|
||
|
default: // check common entity attributes
|
||
|
helpers.checkCommonEntityProperties(entity, curr);
|
||
|
break;
|
||
|
}
|
||
|
curr = scanner.next();
|
||
|
}
|
||
|
|
||
|
return entity;
|
||
|
};
|
||
|
},{"../ParseHelpers":4}],16:[function(require,module,exports){
|
||
|
|
||
|
var helpers = require('../ParseHelpers');
|
||
|
var VertexParser = require('./vertex');
|
||
|
|
||
|
module.exports = EntityParser;
|
||
|
|
||
|
function EntityParser() {}
|
||
|
|
||
|
EntityParser.ForEntityName = 'POLYLINE';
|
||
|
|
||
|
EntityParser.prototype.parseEntity = function(scanner, curr) {
|
||
|
var entity = { type: curr.value, vertices: [] };
|
||
|
curr = scanner.next();
|
||
|
while(curr !== 'EOF') {
|
||
|
if(curr.code === 0) break;
|
||
|
|
||
|
switch(curr.code) {
|
||
|
case 10: // always 0
|
||
|
case 20: // always 0
|
||
|
case 30: // elevation
|
||
|
case 39: // thickness
|
||
|
entity.thickness = curr.value;
|
||
|
break;
|
||
|
case 40: // start width
|
||
|
case 41: // end width
|
||
|
break;
|
||
|
case 70:
|
||
|
entity.shape = (curr.value & 1) !== 0;
|
||
|
entity.includesCurveFitVertices = (curr.value & 2) !== 0;
|
||
|
entity.includesSplineFitVertices = (curr.value & 4) !== 0;
|
||
|
entity.is3dPolyline = (curr.value & 8) !== 0;
|
||
|
entity.is3dPolygonMesh = (curr.value & 16) !== 0;
|
||
|
entity.is3dPolygonMeshClosed = (curr.value & 32) !== 0; // 32 = The polygon mesh is closed in the N direction
|
||
|
entity.isPolyfaceMesh = (curr.value & 64) !== 0;
|
||
|
entity.hasContinuousLinetypePattern = (curr.value & 128) !== 0;
|
||
|
break;
|
||
|
case 71: // Polygon mesh M vertex count
|
||
|
case 72: // Polygon mesh N vertex count
|
||
|
case 73: // Smooth surface M density
|
||
|
case 74: // Smooth surface N density
|
||
|
case 75: // Curves and smooth surface type
|
||
|
break;
|
||
|
case 210:
|
||
|
extrusionDirection = helpers.parsePoint(scanner);
|
||
|
break;
|
||
|
default:
|
||
|
helpers.checkCommonEntityProperties(entity, curr);
|
||
|
break;
|
||
|
}
|
||
|
curr = scanner.next();
|
||
|
}
|
||
|
|
||
|
entity.vertices = parsePolylineVertices(scanner, curr);
|
||
|
|
||
|
return entity;
|
||
|
};
|
||
|
|
||
|
function parsePolylineVertices(scanner, curr) {
|
||
|
var vertexParser = new VertexParser();
|
||
|
|
||
|
var vertices = [];
|
||
|
while (!scanner.isEOF()) {
|
||
|
if (curr.code === 0) {
|
||
|
if (curr.value === 'VERTEX') {
|
||
|
vertices.push(vertexParser.parseEntity(scanner, curr));
|
||
|
curr = scanner.lastReadGroup;
|
||
|
} else if (curr.value === 'SEQEND') {
|
||
|
parseSeqEnd(scanner, curr);
|
||
|
break;
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
return vertices;
|
||
|
};
|
||
|
|
||
|
function parseSeqEnd(scanner, curr) {
|
||
|
var entity = { type: curr.value };
|
||
|
curr = scanner.next();
|
||
|
while(curr != 'EOF') {
|
||
|
if (curr.code == 0) break;
|
||
|
helpers.checkCommonEntityProperties(entity, curr);
|
||
|
curr = scanner.next();
|
||
|
}
|
||
|
|
||
|
return entity;
|
||
|
};
|
||
|
|
||
|
},{"../ParseHelpers":4,"./vertex":20}],17:[function(require,module,exports){
|
||
|
|
||
|
var helpers = require('../ParseHelpers');
|
||
|
|
||
|
module.exports = EntityParser;
|
||
|
|
||
|
function EntityParser() {}
|
||
|
|
||
|
EntityParser.ForEntityName = 'SOLID';
|
||
|
|
||
|
EntityParser.prototype.parseEntity = function(scanner, currentGroup) {
|
||
|
var entity;
|
||
|
entity = { type: currentGroup.value };
|
||
|
entity.points = [];
|
||
|
currentGroup = scanner.next();
|
||
|
while(currentGroup !== 'EOF') {
|
||
|
if(currentGroup.code === 0) break;
|
||
|
|
||
|
switch(currentGroup.code) {
|
||
|
case 10:
|
||
|
entity.points[0] = helpers.parsePoint(scanner);
|
||
|
break;
|
||
|
case 11:
|
||
|
entity.points[1] = helpers.parsePoint(scanner);
|
||
|
break;
|
||
|
case 12:
|
||
|
entity.points[2] = helpers.parsePoint(scanner);
|
||
|
break;
|
||
|
case 13:
|
||
|
entity.points[3] = helpers.parsePoint(scanner);
|
||
|
break;
|
||
|
case 210:
|
||
|
entity.extrusionDirection = helpers.parsePoint(scanner);
|
||
|
break;
|
||
|
default: // check common entity attributes
|
||
|
helpers.checkCommonEntityProperties(entity, currentGroup);
|
||
|
break;
|
||
|
}
|
||
|
currentGroup = scanner.next();
|
||
|
}
|
||
|
|
||
|
return entity;
|
||
|
};
|
||
|
},{"../ParseHelpers":4}],18:[function(require,module,exports){
|
||
|
|
||
|
var helpers = require('../ParseHelpers');
|
||
|
|
||
|
module.exports = EntityParser;
|
||
|
|
||
|
function EntityParser() {}
|
||
|
|
||
|
EntityParser.ForEntityName = 'SPLINE';
|
||
|
|
||
|
EntityParser.prototype.parseEntity = function(scanner, curr) {
|
||
|
var entity;
|
||
|
entity = { type: curr.value };
|
||
|
curr = scanner.next();
|
||
|
while(curr !== 'EOF')
|
||
|
{
|
||
|
if(curr.code === 0) break;
|
||
|
|
||
|
switch(curr.code) {
|
||
|
case 10:
|
||
|
if (!entity.controlPoints) entity.controlPoints = [];
|
||
|
entity.controlPoints.push(helpers.parsePoint(scanner));
|
||
|
break;
|
||
|
case 11:
|
||
|
if (!entity.fitPoints) entity.fitPoints = [];
|
||
|
entity.fitPoints.push(helpers.parsePoint(scanner));
|
||
|
break;
|
||
|
case 12:
|
||
|
entity.startTangent = helpers.parsePoint(scanner);
|
||
|
break;
|
||
|
case 13:
|
||
|
entity.endTangent = helpers.parsePoint(scanner);
|
||
|
break;
|
||
|
case 40:
|
||
|
if (!entity.knotValues) entity.knotValues = [];
|
||
|
entity.knotValues.push(curr.value);
|
||
|
break;
|
||
|
case 70:
|
||
|
if ((curr.value & 1) != 0) entity.closed = true;
|
||
|
if ((curr.value & 2) != 0) entity.periodic = true;
|
||
|
if ((curr.value & 4) != 0) entity.rational = true;
|
||
|
if ((curr.value & 8) != 0) entity.planar = true;
|
||
|
if ((curr.value & 16) != 0)
|
||
|
{
|
||
|
entity.planar = true;
|
||
|
entity.linear = true;
|
||
|
}
|
||
|
break;
|
||
|
|
||
|
case 71:
|
||
|
entity.degreeOfSplineCurve = curr.value;
|
||
|
break;
|
||
|
case 72:
|
||
|
entity.numberOfKnots = curr.value;
|
||
|
break;
|
||
|
case 73:
|
||
|
entity.numberOfControlPoints = curr.value;
|
||
|
break;
|
||
|
case 74:
|
||
|
entity.numberOfFitPoints = curr.value;
|
||
|
break;
|
||
|
case 210:
|
||
|
entity.normalVector = helpers.parsePoint(scanner);
|
||
|
break;
|
||
|
default:
|
||
|
helpers.checkCommonEntityProperties(entity, curr);
|
||
|
break;
|
||
|
}
|
||
|
curr = scanner.next();
|
||
|
}
|
||
|
|
||
|
return entity;
|
||
|
};
|
||
|
},{"../ParseHelpers":4}],19:[function(require,module,exports){
|
||
|
|
||
|
var helpers = require('../ParseHelpers');
|
||
|
|
||
|
module.exports = EntityParser;
|
||
|
|
||
|
function EntityParser() {}
|
||
|
|
||
|
EntityParser.ForEntityName = 'TEXT';
|
||
|
|
||
|
EntityParser.prototype.parseEntity = function(scanner, curr) {
|
||
|
var entity;
|
||
|
entity = { type: curr.value };
|
||
|
curr = scanner.next();
|
||
|
while(curr !== 'EOF') {
|
||
|
if(curr.code === 0) break;
|
||
|
switch(curr.code) {
|
||
|
case 10: // X coordinate of 'first alignment point'
|
||
|
entity.startPoint = helpers.parsePoint(scanner);
|
||
|
break;
|
||
|
case 11: // X coordinate of 'second alignment point'
|
||
|
entity.endPoint = helpers.parsePoint(scanner);
|
||
|
break;
|
||
|
case 40: // Text height
|
||
|
entity.textHeight = curr.value;
|
||
|
break;
|
||
|
case 41:
|
||
|
entity.xScale = curr.value;
|
||
|
break;
|
||
|
case 50: // Rotation in degrees
|
||
|
entity.rotation = curr.value;
|
||
|
break;
|
||
|
case 1: // Text
|
||
|
entity.text = curr.value;
|
||
|
break;
|
||
|
// NOTE: 72 and 73 are meaningless without 11 (second alignment point)
|
||
|
case 72: // Horizontal alignment
|
||
|
entity.halign = curr.value;
|
||
|
break;
|
||
|
case 73: // Vertical alignment
|
||
|
entity.valign = curr.value;
|
||
|
break;
|
||
|
default: // check common entity attributes
|
||
|
helpers.checkCommonEntityProperties(entity, curr);
|
||
|
break;
|
||
|
}
|
||
|
curr = scanner.next();
|
||
|
}
|
||
|
return entity;
|
||
|
};
|
||
|
},{"../ParseHelpers":4}],20:[function(require,module,exports){
|
||
|
|
||
|
var helpers = require('../ParseHelpers');
|
||
|
|
||
|
module.exports = EntityParser;
|
||
|
|
||
|
function EntityParser() {}
|
||
|
|
||
|
EntityParser.ForEntityName = 'VERTEX';
|
||
|
|
||
|
EntityParser.prototype.parseEntity = function(scanner, curr) {
|
||
|
var entity = { type: curr.value };
|
||
|
curr = scanner.next();
|
||
|
while(curr !== 'EOF') {
|
||
|
if(curr.code === 0) break;
|
||
|
|
||
|
switch(curr.code) {
|
||
|
case 10: // X
|
||
|
entity.x = curr.value;
|
||
|
break;
|
||
|
case 20: // Y
|
||
|
entity.y = curr.value;
|
||
|
break;
|
||
|
case 30: // Z
|
||
|
entity.z = curr.value;
|
||
|
break;
|
||
|
case 40: // start width
|
||
|
case 41: // end width
|
||
|
case 42: // bulge
|
||
|
if(curr.value != 0) entity.bulge = curr.value;
|
||
|
break;
|
||
|
case 70: // flags
|
||
|
entity.curveFittingVertex = (curr.value & 1) !== 0;
|
||
|
entity.curveFitTangent = (curr.value & 2) !== 0;
|
||
|
entity.splineVertex = (curr.value & 8) !== 0;
|
||
|
entity.splineControlPoint = (curr.value & 16) !== 0;
|
||
|
entity.threeDPolylineVertex = (curr.value & 32) !== 0;
|
||
|
entity.threeDPolylineMesh = (curr.value & 64) !== 0;
|
||
|
entity.polyfaceMeshVertex = (curr.value & 128) !== 0;
|
||
|
break;
|
||
|
case 50: // curve fit tangent direction
|
||
|
case 71: // polyface mesh vertex index
|
||
|
case 72: // polyface mesh vertex index
|
||
|
case 73: // polyface mesh vertex index
|
||
|
case 74: // polyface mesh vertex index
|
||
|
break;
|
||
|
default:
|
||
|
helpers.checkCommonEntityProperties(entity, curr);
|
||
|
break;
|
||
|
}
|
||
|
|
||
|
curr = scanner.next();
|
||
|
}
|
||
|
return entity;
|
||
|
};
|
||
|
},{"../ParseHelpers":4}],21:[function(require,module,exports){
|
||
|
/*
|
||
|
* loglevel - https://github.com/pimterry/loglevel
|
||
|
*
|
||
|
* Copyright (c) 2013 Tim Perry
|
||
|
* Licensed under the MIT license.
|
||
|
*/
|
||
|
(function (root, definition) {
|
||
|
if (typeof module === 'object' && module.exports && typeof require === 'function') {
|
||
|
module.exports = definition();
|
||
|
} else if (typeof define === 'function' && typeof define.amd === 'object') {
|
||
|
define(definition);
|
||
|
} else {
|
||
|
root.log = definition();
|
||
|
}
|
||
|
}(this, function () {
|
||
|
var self = {};
|
||
|
var noop = function() {};
|
||
|
var undefinedType = "undefined";
|
||
|
|
||
|
function realMethod(methodName) {
|
||
|
if (typeof console === undefinedType) {
|
||
|
return false; // We can't build a real method without a console to log to
|
||
|
} else if (console[methodName] !== undefined) {
|
||
|
return bindMethod(console, methodName);
|
||
|
} else if (console.log !== undefined) {
|
||
|
return bindMethod(console, 'log');
|
||
|
} else {
|
||
|
return noop;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
function bindMethod(obj, methodName) {
|
||
|
var method = obj[methodName];
|
||
|
if (typeof method.bind === 'function') {
|
||
|
return method.bind(obj);
|
||
|
} else {
|
||
|
try {
|
||
|
return Function.prototype.bind.call(method, obj);
|
||
|
} catch (e) {
|
||
|
// Missing bind shim or IE8 + Modernizr, fallback to wrapping
|
||
|
return function() {
|
||
|
return Function.prototype.apply.apply(method, [obj, arguments]);
|
||
|
};
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
function enableLoggingWhenConsoleArrives(methodName, level) {
|
||
|
return function () {
|
||
|
if (typeof console !== undefinedType) {
|
||
|
replaceLoggingMethods(level);
|
||
|
self[methodName].apply(self, arguments);
|
||
|
}
|
||
|
};
|
||
|
}
|
||
|
|
||
|
var logMethods = [
|
||
|
"trace",
|
||
|
"debug",
|
||
|
"info",
|
||
|
"warn",
|
||
|
"error"
|
||
|
];
|
||
|
|
||
|
function replaceLoggingMethods(level) {
|
||
|
for (var i = 0; i < logMethods.length; i++) {
|
||
|
var methodName = logMethods[i];
|
||
|
self[methodName] = (i < level) ? noop : self.methodFactory(methodName, level);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
function persistLevelIfPossible(levelNum) {
|
||
|
var levelName = (logMethods[levelNum] || 'silent').toUpperCase();
|
||
|
|
||
|
// Use localStorage if available
|
||
|
try {
|
||
|
window.localStorage['loglevel'] = levelName;
|
||
|
return;
|
||
|
} catch (ignore) {}
|
||
|
|
||
|
// Use session cookie as fallback
|
||
|
try {
|
||
|
window.document.cookie = "loglevel=" + levelName + ";";
|
||
|
} catch (ignore) {}
|
||
|
}
|
||
|
|
||
|
function loadPersistedLevel() {
|
||
|
var storedLevel;
|
||
|
|
||
|
try {
|
||
|
storedLevel = window.localStorage['loglevel'];
|
||
|
} catch (ignore) {}
|
||
|
|
||
|
if (typeof storedLevel === undefinedType) {
|
||
|
try {
|
||
|
storedLevel = /loglevel=([^;]+)/.exec(window.document.cookie)[1];
|
||
|
} catch (ignore) {}
|
||
|
}
|
||
|
|
||
|
if (self.levels[storedLevel] === undefined) {
|
||
|
storedLevel = "WARN";
|
||
|
}
|
||
|
|
||
|
self.setLevel(self.levels[storedLevel], false);
|
||
|
}
|
||
|
|
||
|
/*
|
||
|
*
|
||
|
* Public API
|
||
|
*
|
||
|
*/
|
||
|
|
||
|
self.levels = { "TRACE": 0, "DEBUG": 1, "INFO": 2, "WARN": 3,
|
||
|
"ERROR": 4, "SILENT": 5};
|
||
|
|
||
|
self.methodFactory = function (methodName, level) {
|
||
|
return realMethod(methodName) ||
|
||
|
enableLoggingWhenConsoleArrives(methodName, level);
|
||
|
};
|
||
|
|
||
|
self.setLevel = function (level, persist) {
|
||
|
if (typeof level === "string" && self.levels[level.toUpperCase()] !== undefined) {
|
||
|
level = self.levels[level.toUpperCase()];
|
||
|
}
|
||
|
if (typeof level === "number" && level >= 0 && level <= self.levels.SILENT) {
|
||
|
if (persist !== false) { // defaults to true
|
||
|
persistLevelIfPossible(level);
|
||
|
}
|
||
|
replaceLoggingMethods(level);
|
||
|
if (typeof console === undefinedType && level < self.levels.SILENT) {
|
||
|
return "No console available for logging";
|
||
|
}
|
||
|
} else {
|
||
|
throw "log.setLevel() called with invalid level: " + level;
|
||
|
}
|
||
|
};
|
||
|
|
||
|
self.enableAll = function(persist) {
|
||
|
self.setLevel(self.levels.TRACE, persist);
|
||
|
};
|
||
|
|
||
|
self.disableAll = function(persist) {
|
||
|
self.setLevel(self.levels.SILENT, persist);
|
||
|
};
|
||
|
|
||
|
// Grab the current global log variable in case of overwrite
|
||
|
var _log = (typeof window !== undefinedType) ? window.log : undefined;
|
||
|
self.noConflict = function() {
|
||
|
if (typeof window !== undefinedType &&
|
||
|
window.log === self) {
|
||
|
window.log = _log;
|
||
|
}
|
||
|
|
||
|
return self;
|
||
|
};
|
||
|
|
||
|
loadPersistedLevel();
|
||
|
return self;
|
||
|
}));
|
||
|
|
||
|
},{}]},{},[3])(3)
|
||
|
});
|