@mlightcad/libdxfrw-converter
Version:
The `libdxfrw-converter` package provides a DWG file converter for the RealDWG-Web ecosystem, enabling reading and conversion of DWG files into the AutoCAD-like drawing database structure. It is based on the [libdxfrw](https://github.com/LibreDWG/libdxfrw
488 lines • 23.6 kB
JavaScript
var __extends = (this && this.__extends) || (function () {
var extendStatics = function (d, b) {
extendStatics = Object.setPrototypeOf ||
({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) ||
function (d, b) { for (var p in b) if (Object.prototype.hasOwnProperty.call(b, p)) d[p] = b[p]; };
return extendStatics(d, b);
};
return function (d, b) {
if (typeof b !== "function" && b !== null)
throw new TypeError("Class extends value " + String(b) + " is not a constructor or null");
extendStatics(d, b);
function __() { this.constructor = d; }
d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());
};
})();
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
return new (P || (P = Promise))(function (resolve, reject) {
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
step((generator = generator.apply(thisArg, _arguments || [])).next());
});
};
var __generator = (this && this.__generator) || function (thisArg, body) {
var _ = { label: 0, sent: function() { if (t[0] & 1) throw t[1]; return t[1]; }, trys: [], ops: [] }, f, y, t, g;
return g = { next: verb(0), "throw": verb(1), "return": verb(2) }, typeof Symbol === "function" && (g[Symbol.iterator] = function() { return this; }), g;
function verb(n) { return function (v) { return step([n, v]); }; }
function step(op) {
if (f) throw new TypeError("Generator is already executing.");
while (g && (g = 0, op[0] && (_ = 0)), _) try {
if (f = 1, y && (t = op[0] & 2 ? y["return"] : op[0] ? y["throw"] || ((t = y["return"]) && t.call(y), 0) : y.next) && !(t = t.call(y, op[1])).done) return t;
if (y = 0, t) op = [op[0] & 2, t.value];
switch (op[0]) {
case 0: case 1: t = op; break;
case 4: _.label++; return { value: op[1], done: false };
case 5: _.label++; y = op[1]; op = [0]; continue;
case 7: op = _.ops.pop(); _.trys.pop(); continue;
default:
if (!(t = _.trys, t = t.length > 0 && t[t.length - 1]) && (op[0] === 6 || op[0] === 2)) { _ = 0; continue; }
if (op[0] === 3 && (!t || (op[1] > t[0] && op[1] < t[3]))) { _.label = op[1]; break; }
if (op[0] === 6 && _.label < t[1]) { _.label = t[1]; t = op; break; }
if (t && _.label < t[2]) { _.label = t[2]; _.ops.push(op); break; }
if (t[2]) _.ops.pop();
_.trys.pop(); continue;
}
op = body.call(thisArg, _);
} catch (e) { op = [6, e]; y = 0; } finally { f = t = 0; }
if (op[0] & 5) throw op[1]; return { value: op[0] ? op[1] : void 0, done: true };
}
};
import { AcCmColor, AcDbBatchProcessing, AcDbBlockTableRecord, AcDbDatabaseConverter, AcDbDimStyleTableRecord, AcDbLayerTableRecord, AcDbLinetypeTableRecord, AcDbTextStyleTableRecord, AcDbViewportTableRecord, ByLayer, DEFAULT_TEXT_STYLE } from '@mlightcad/data-model';
import { AcDbEntityConverter } from './AcDbEntitiyConverter';
import { AcDbObjectConverter } from './AcDbObjectConverter';
/**
* Database converter for DWG files based on [libdxfrw-web](https://github.com/mlight-lee/libdxfrw).
* @internal
*/
var AcDbLibdxfrwConverter = /** @class */ (function (_super) {
__extends(AcDbLibdxfrwConverter, _super);
function AcDbLibdxfrwConverter(instance) {
var _this = _super.call(this) || this;
_this.librefrw = instance;
return _this;
}
AcDbLibdxfrwConverter.prototype.onFinished = function () {
_super.prototype.onFinished.call(this);
if (this.dwg) {
this.dwg.delete();
this.dwg = undefined;
}
if (this.database) {
this.database.delete();
this.database = undefined;
}
if (this.fileHandler) {
this.fileHandler.delete();
this.fileHandler = undefined;
}
};
AcDbLibdxfrwConverter.prototype.parse = function (data) {
return __awaiter(this, void 0, void 0, function () {
var libdxfrw;
return __generator(this, function (_a) {
if (this.librefrw == null) {
throw new Error('librefrw is not loaded!');
}
libdxfrw = this.librefrw;
this.database = new libdxfrw.DRW_Database();
this.fileHandler = new libdxfrw.DRW_FileHandler();
this.fileHandler.database = this.database;
this.dwg = new libdxfrw.DRW_DwgR(data);
// Uncomment out the following line if you want to show debug info
// this.dwg.setDebug(libdxfrw.DRW_dbg_Level.Debug);
this.dwg.read(this.fileHandler, false);
return [2 /*return*/, {
model: this.database,
data: {
unknownEntityCount: 0
}
}];
});
});
};
AcDbLibdxfrwConverter.prototype.processLineTypes = function (model, db) {
var lineTypes = model.lineTypes;
for (var index = 0, size = lineTypes.size(); index < size; ++index) {
var item = lineTypes.get(index);
if (item != null) {
var lineType = {
name: item.name,
description: item.desc,
standardFlag: item.flags,
totalPatternLength: item.length,
pattern: this.convertLineTypePattern(item.path)
};
var record = new AcDbLinetypeTableRecord(lineType);
this.processCommonTableEntryAttrs(item, record);
record.name = item.name;
db.tables.linetypeTable.add(record);
}
}
};
AcDbLibdxfrwConverter.prototype.convertLineTypePattern = function (path) {
var pattern = [];
for (var index = 0, size = path.size(); index < size; ++index) {
// libdxfrw doesn't support complex line type and always convert complex line type to simple line type
pattern.push({
elementLength: path.get(index) || 0,
elementTypeFlag: 0
});
}
return pattern;
};
AcDbLibdxfrwConverter.prototype.processTextStyles = function (model, db) {
var textStyles = model.textStyles;
for (var index = 0, size = textStyles.size(); index < size; ++index) {
var item = textStyles.get(index);
if (item != null) {
var textStyle = {
name: item.name,
standardFlag: item.flags,
fixedTextHeight: item.height,
widthFactor: item.width,
obliqueAngle: item.oblique,
textGenerationFlag: item.genFlag,
lastHeight: item.lastHeight,
font: item.font,
bigFont: item.bigFont
};
var record = new AcDbTextStyleTableRecord(textStyle);
this.processCommonTableEntryAttrs(item, record);
db.tables.textStyleTable.add(record);
}
}
db.ensureTextStyleDefaults();
};
AcDbLibdxfrwConverter.prototype.processDimStyles = function (model, db) {
var dimStyles = model.dimStyles;
for (var index = 0, size = dimStyles.size(); index < size; ++index) {
var item = dimStyles.get(index);
if (item != null) {
var attrs = {
name: item.name,
ownerId: item.parentHandle.toString(),
dimpost: item.dimpost || '',
dimapost: item.dimapost || '',
dimscale: item.dimscale,
dimasz: item.dimasz,
dimexo: item.dimexo,
dimdli: item.dimdli,
dimexe: item.dimexe,
dimrnd: item.dimrnd,
dimdle: item.dimdle,
dimtp: item.dimtp,
dimtm: item.dimtm,
dimtxt: item.dimtxt,
dimcen: item.dimcen,
dimtsz: item.dimtsz,
dimaltf: item.dimaltf,
dimlfac: item.dimlfac,
dimtvp: item.dimtvp,
dimtfac: item.dimtfac,
dimgap: item.dimgap,
dimaltrnd: item.dimaltrnd,
dimtol: item.dimtol == null || item.dimtol == 0 ? 0 : 1,
dimlim: item.dimlim == null || item.dimlim == 0 ? 0 : 1,
dimtih: item.dimtih == null || item.dimtih == 0 ? 0 : 1,
dimtoh: item.dimtoh == null || item.dimtoh == 0 ? 0 : 1,
dimse1: item.dimse1 == null || item.dimse1 == 0 ? 0 : 1,
dimse2: item.dimse2 == null || item.dimse2 == 0 ? 0 : 1,
dimtad: item.dimtad,
dimzin: item.dimzin,
dimazin: item.dimazin,
dimalt: item.dimalt,
dimaltd: item.dimaltd,
dimtofl: item.dimtofl,
dimsah: item.dimsah,
dimtix: item.dimtix,
dimsoxd: item.dimsoxd,
dimclrd: item.dimclrd,
dimclre: item.dimclre,
dimclrt: item.dimclrt,
dimadec: item.dimadec || 0,
dimunit: item.dimunit || 2,
dimdec: item.dimdec,
dimtdec: item.dimtdec,
dimaltu: item.dimaltu,
dimalttd: item.dimalttd,
dimaunit: item.dimaunit,
dimfrac: item.dimfrac,
dimlunit: item.dimlunit,
dimdsep: item.dimdsep.toString(),
dimtmove: item.dimtmove || 0,
dimjust: item.dimjust,
dimsd1: item.dimsd1,
dimsd2: item.dimsd2,
dimtolj: item.dimtolj,
dimtzin: item.dimtzin,
dimaltz: item.dimaltz,
dimalttz: item.dimaltttz,
dimfit: item.dimfit || 0,
dimupt: item.dimupt,
dimatfit: item.dimatfit,
dimtxsty: item.dimtxsty || DEFAULT_TEXT_STYLE,
dimldrblk: item.dimldrblk || '',
dimblk: item.dimblk || '',
dimblk1: item.dimblk1 || '',
dimblk2: item.dimblk2 || '',
dimlwd: item.dimlwd,
dimlwe: item.dimlwe
};
var record = new AcDbDimStyleTableRecord(attrs);
this.processCommonTableEntryAttrs(item, record);
db.tables.dimStyleTable.add(record);
}
}
};
AcDbLibdxfrwConverter.prototype.processLayers = function (model, db) {
var layers = model.layers;
for (var index = 0, size = layers.size(); index < size; ++index) {
var item = layers.get(index);
if (item != null) {
var color = new AcCmColor();
color.colorIndex = item.color;
var record = new AcDbLayerTableRecord({
name: item.name,
standardFlags: item.flags,
linetype: item.lineType,
lineWeight: item.lWeight,
isOff: item.color < 0,
color: color,
isPlottable: item.plotF,
materialId: item.handleMaterialS
});
this.processCommonTableEntryAttrs(item, record);
db.tables.layerTable.add(record);
}
}
};
AcDbLibdxfrwConverter.prototype.processViewports = function (model, db) {
var viewports = model.viewports;
for (var index = 0, size = viewports.size(); index < size; ++index) {
var item = viewports.get(index);
if (item != null) {
var record = new AcDbViewportTableRecord();
this.processCommonTableEntryAttrs(item, record);
if (item.circleZoom) {
record.circleSides = item.circleZoom;
}
record.standardFlag = item.flags;
record.center.copy(item.center);
record.lowerLeftCorner.copy(item.lowerLeft);
record.upperRightCorner.copy(item.upperRight);
if (item.snapBase) {
record.snapBase.copy(item.snapBase);
}
if (item.snapAngle) {
record.snapAngle = item.snapAngle;
}
if (record.snapIncrements) {
record.snapIncrements.copy(item.snapSpacing);
}
if (item.gridSpacing) {
record.gridIncrements.copy(item.gridSpacing);
}
record.gsView.center.copy(item.center);
record.gsView.viewDirectionFromTarget.copy(item.viewDir);
record.gsView.viewTarget.copy(item.viewTarget);
if (item.lensHeight) {
record.gsView.lensLength = item.lensHeight;
}
if (item.height) {
record.gsView.viewHeight = item.height;
}
if (item.twistAngle) {
record.gsView.viewTwistAngle = item.twistAngle;
}
if (item.viewMode) {
record.gsView.viewMode = item.viewMode;
}
if (item.ucsIcon) {
record.gsView.ucsIconSetting = item.ucsIcon;
}
db.tables.viewportTable.add(record);
}
}
};
AcDbLibdxfrwConverter.prototype.processBlockTables = function (model, db) {
var blocks = model.blocks;
for (var index = 0, size = blocks.size(); index < size; ++index) {
var block = blocks.get(index);
if (block != null) {
var dbBlock = new AcDbBlockTableRecord();
dbBlock.objectId = block.handle.toString();
dbBlock.name = block.name.toUpperCase();
// TODO: Add logic to set the associated layout id
db.tables.blockTable.add(dbBlock);
if (block.entities) {
this.processEntitiesInBlock(block.entities, dbBlock);
}
}
}
};
AcDbLibdxfrwConverter.prototype.processCommonTableEntryAttrs = function (entry, dbEntry) {
dbEntry.name = entry.name;
dbEntry.objectId = entry.handle.toString();
if (entry.parentHandle != null) {
dbEntry.ownerId = entry.parentHandle.toString();
}
};
AcDbLibdxfrwConverter.prototype.processHeader = function (model, db) {
var header = model.header;
// TODO: Check not supported versions
var variant = header.getVar('$CECOLOR');
// Initial value: ByLayer, Color index 256 is 'ByLayer'
db.cecolor.colorIndex = variant ? variant.getInt() : 256;
variant = header.getVar('$ANGDIR');
// Initial value: 0
db.angdir = variant ? variant.getInt() : 0;
variant = header.getVar('$AUNITS');
// Initial value: 0
db.aunits = variant ? variant.getInt() : 0;
variant = header.getVar('$CELTYPE');
// Initial value: BYLAYER
db.celtype = variant ? variant.getString() : ByLayer;
variant = header.getVar('$INSUNITS');
// Initial value: 1 (imperial) or 4 (metric)
db.insunits = variant ? variant.getInt() : 1;
variant = header.getVar('$UNITMODE');
if (variant)
db.unitmode = variant.getInt();
variant = header.getVar('$MEASUREMENT');
if (variant)
db.measurement = variant.getInt();
variant = header.getVar('$PDMODE');
// Initial value: 0
db.pdmode = variant ? variant.getInt() : 0;
variant = header.getVar('$PDSIZE');
// Initial value: 0
db.pdsize = variant ? variant.getDouble() : 0.0;
};
AcDbLibdxfrwConverter.prototype.processObjects = function (model, db) {
this.processImageDefs(model.images, db);
};
AcDbLibdxfrwConverter.prototype.processImageDefs = function (imageDefs, db) {
var objectConverter = new AcDbObjectConverter();
var imageDefDict = db.objects.imageDefinition;
for (var index = 0, size = imageDefs.size(); index < size; ++index) {
var item = imageDefs.get(index);
if (item != null) {
var dbImageDef = objectConverter.convertImageDef(item);
imageDefDict.setAt(dbImageDef.objectId, dbImageDef);
}
}
};
AcDbLibdxfrwConverter.prototype.processEntitiesInBlock = function (entities, blockTableRecord) {
return __awaiter(this, void 0, void 0, function () {
var converter, dbEntities, index, size, entity, dbEntity;
return __generator(this, function (_a) {
converter = new AcDbEntityConverter();
dbEntities = [];
for (index = 0, size = entities.size(); index < size; ++index) {
entity = entities.get(index);
if (entity != null) {
dbEntity = converter.convert(entity);
if (dbEntity) {
dbEntities.push(dbEntity);
}
}
}
// Use batch append to improve performance
blockTableRecord.appendEntity(dbEntities);
return [2 /*return*/];
});
});
};
AcDbLibdxfrwConverter.prototype.processEntities = function (model, db, minimumChunkSize, startPercentage, progress) {
return __awaiter(this, void 0, void 0, function () {
var converter_1, entities_1, entityList, entityCount_1, i, entity, batchProcessor, blockTableRecord_1;
var _this = this;
return __generator(this, function (_a) {
switch (_a.label) {
case 0:
if (!model.mBlock) return [3 /*break*/, 2];
converter_1 = new AcDbEntityConverter();
entities_1 = [];
entityList = model.mBlock.entities;
entityCount_1 = entityList.size();
for (i = 0; i < entityCount_1; i++) {
entity = entityList.get(i);
if (entity)
entities_1.push(entity);
}
batchProcessor = new AcDbBatchProcessing(entities_1.length, 100 - startPercentage.value, minimumChunkSize);
// Groups entities by their `type` property and flattens the result into a single array.
if (this.config.convertByEntityType) {
entities_1 = this.groupAndFlattenByType(entities_1);
}
blockTableRecord_1 = db.tables.blockTable.modelSpace;
return [4 /*yield*/, batchProcessor.processChunk(function (start, end) { return __awaiter(_this, void 0, void 0, function () {
var dbEntities, i, entity, dbEntity, percentage;
return __generator(this, function (_a) {
switch (_a.label) {
case 0:
dbEntities = [];
for (i = start; i < end; i++) {
entity = entities_1[i];
dbEntity = converter_1.convert(entity);
if (dbEntity) {
dbEntities.push(dbEntity);
}
}
// Use batch append to improve performance
blockTableRecord_1.appendEntity(dbEntities);
if (!progress) return [3 /*break*/, 2];
percentage = startPercentage.value +
(end / entityCount_1) * (100 - startPercentage.value);
if (percentage > 100)
percentage = 100;
return [4 /*yield*/, progress(percentage, 'ENTITY', 'IN-PROGRESS')];
case 1:
_a.sent();
_a.label = 2;
case 2: return [2 /*return*/];
}
});
}); })];
case 1:
_a.sent();
_a.label = 2;
case 2: return [2 /*return*/];
}
});
});
};
/**
* Groups entities by their `type` property and flattens the result into a single array.
*
* The order of `type` groups follows the order in which they first appear in the input array.
* Items within each group preserve their original order.
*
* This runs in O(n) time, which is generally faster than sorting when you
* don't care about alphabetical order of types.
*
* @param entities - The array of entities to group and flatten.
*
* @returns A new array of entities grouped by their `type` property.
*/
AcDbLibdxfrwConverter.prototype.groupAndFlattenByType = function (entities) {
var groups = {};
var order = [];
var length = entities.length;
for (var i = 0; i < length; i++) {
var entity = entities[i];
var entityType = entity.eType.value;
if (!groups[entityType]) {
groups[entityType] = [];
order.push(entityType);
}
groups[entityType].push(entity);
}
return order.flatMap(function (type) { return groups[type]; });
};
return AcDbLibdxfrwConverter;
}(AcDbDatabaseConverter));
export { AcDbLibdxfrwConverter };
//# sourceMappingURL=AcDbLibdxfrwConverter.js.map