UNPKG

@mlightcad/libredwg-converter

Version:

The `libredwg-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 [LibreDWG](https://www.gnu.org/software/libredw

1,016 lines (1,015 loc) 54.4 kB
var __assign = (this && this.__assign) || function () { __assign = Object.assign || function(t) { for (var s, i = 1, n = arguments.length; i < n; i++) { s = arguments[i]; for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p)) t[p] = s[p]; } return t; }; return __assign.apply(this, arguments); }; var __values = (this && this.__values) || function(o) { var s = typeof Symbol === "function" && Symbol.iterator, m = s && o[s], i = 0; if (m) return m.call(o); if (o && typeof o.length === "number") return { next: function () { if (o && i >= o.length) o = void 0; return { value: o && o[i++], done: !o }; } }; throw new TypeError(s ? "Object is not iterable." : "Symbol.iterator is not defined."); }; import { AcCmColor, AcCmTransparency, AcDb2dPolyline, AcDb3dPolyline, AcDb3PointAngularDimension, AcDbAlignedDimension, AcDbArc, AcDbAttribute, AcDbAttributeDefinition, AcDbAttributeFlags, AcDbAttributeMTextFlag, AcDbBlockReference, AcDbCircle, AcDbDiametricDimension, AcDbEllipse, AcDbFace, AcDbHatch, AcDbHatchObjectType, AcDbLeader, AcDbLine, AcDbMLeader, AcDbMLeaderContentType, AcDbMLeaderLineType, AcDbMLine, AcDbMText, AcDbOrdinateDimension, AcDbPoint, AcDbPoly2dType, AcDbPoly3dType, AcDbPolyFaceMesh, AcDbPolygonMesh, AcDbPolyline, AcDbRadialDimension, AcDbRasterImage, AcDbRay, AcDbRotatedDimension, AcDbSpline, AcDbTable, AcDbText, AcDbTrace, AcDbViewport, AcDbWipeout, AcDbXline, AcGeCircArc2d, AcGeEllipseArc2d, AcGeLine2d, AcGeLoop2d, AcGePoint2d, AcGePoint3d, AcGePolyline2d, AcGeSpline3d, AcGeVector2d, AcGeVector3d, transformOcsPointToWcs } from '@mlightcad/data-model'; var AcDbEntityConverter = /** @class */ (function () { function AcDbEntityConverter() { } AcDbEntityConverter.prototype.convert = function (entity) { var dbEntity = this.createEntity(entity); if (dbEntity) { this.processCommonAttrs(entity, dbEntity); } return dbEntity; }; /** * Create the corresponding drawing database entity from data in dxf format * @param entity Input entity data in dxf format * @returns Return the converted drawing database entity */ AcDbEntityConverter.prototype.createEntity = function (entity) { if (entity.type == '3DFACE') { return this.convertFace(entity); } else if (entity.type == 'ARC') { return this.convertArc(entity); } else if (entity.type == 'ATTDEF') { return this.convertAttributeDefinition(entity); } else if (entity.type == 'ATTRIB') { return this.convertAttribute(entity); } else if (entity.type == 'CIRCLE') { return this.convertCirle(entity); } else if (entity.type == 'DIMENSION') { return this.convertDimension(entity); } else if (entity.type == 'ELLIPSE') { return this.convertEllipse(entity); } else if (entity.type == 'HATCH') { return this.convertHatch(entity); } else if (entity.type == 'IMAGE') { return this.convertImage(entity); } else if (entity.type == 'LEADER') { return this.convertLeader(entity); } else if (entity.type == 'LINE') { return this.convertLine(entity); } else if (entity.type == 'LWPOLYLINE') { return this.convertLWPolyline(entity); } else if (entity.type == 'MLINE') { return this.convertMLine(entity); } else if (entity.type == 'MTEXT') { return this.convertMText(entity); } else if (entity.type == 'MULTILEADER' || entity.type == 'MLEADER') { return this.convertMLeader(entity); } else if (entity.type == 'POINT') { return this.convertPoint(entity); } else if (entity.type == 'POLYLINE2D') { return this.convertPolyline2d(entity); } else if (entity.type == 'POLYLINE3D') { return this.convertPolyline3d(entity); } else if (entity.type == 'RAY') { return this.convertRay(entity); } else if (entity.type == 'SPLINE') { return this.convertSpline(entity); } else if (entity.type == 'ACAD_TABLE') { return this.convertTable(entity); } else if (entity.type == 'TEXT') { return this.convertText(entity); } else if (entity.type == 'SOLID') { return this.convertSolid(entity); } else if (entity.type == 'VIEWPORT') { return this.convertViewport(entity); } else if (entity.type == 'WIPEOUT') { return this.convertWipeout(entity); } else if (entity.type == 'XLINE') { return this.convertXline(entity); } else if (entity.type == 'INSERT') { return this.convertBlockReference(entity); } return null; }; AcDbEntityConverter.prototype.convertFace = function (face) { var dbEntity = new AcDbFace(); if (face.corner1) dbEntity.setVertexAt(0, face.corner1); if (face.corner2) dbEntity.setVertexAt(1, face.corner2); if (face.corner3) dbEntity.setVertexAt(2, face.corner3); if (face.corner4) dbEntity.setVertexAt(3, face.corner4); dbEntity.setEdgeInvisibilities(face.flag); return dbEntity; }; AcDbEntityConverter.prototype.convertArc = function (arc) { var _a; var normal = (_a = arc.extrusionDirection) !== null && _a !== void 0 ? _a : AcGeVector3d.Z_AXIS; var dbEntity = new AcDbArc(transformOcsPointToWcs(arc.center, normal), arc.radius, arc.startAngle, arc.endAngle, normal); return dbEntity; }; AcDbEntityConverter.prototype.convertCirle = function (circle) { var _a; var normal = (_a = circle.extrusionDirection) !== null && _a !== void 0 ? _a : AcGeVector3d.Z_AXIS; var dbEntity = new AcDbCircle(transformOcsPointToWcs(circle.center, normal), circle.radius, normal); return dbEntity; }; AcDbEntityConverter.prototype.convertEllipse = function (ellipse) { var _a; var majorAxis = new AcGeVector3d(ellipse.majorAxisEndPoint); var majorAxisRadius = majorAxis.length(); var dbEntity = new AcDbEllipse(ellipse.center, (_a = ellipse.extrusionDirection) !== null && _a !== void 0 ? _a : AcGeVector3d.Z_AXIS, majorAxis, majorAxisRadius, majorAxisRadius * ellipse.axisRatio, ellipse.startAngle, ellipse.endAngle); return dbEntity; }; AcDbEntityConverter.prototype.convertLine = function (line) { var start = line.startPoint; var end = line.endPoint; var dbEntity = new AcDbLine(new AcGePoint3d(start.x, start.y, start.z), new AcGePoint3d(end.x, end.y, end.z)); return dbEntity; }; AcDbEntityConverter.prototype.convertSpline = function (spline) { // Catch error to construct spline because it maybe one spline in one block. // If don't catch the error, the block conversion may be interruptted. try { if (spline.numberOfControlPoints > 0 && spline.numberOfKnots > 0) { return new AcDbSpline(spline.controlPoints, spline.knots, spline.weights, spline.degree, !!(spline.flag & 0x01)); } else if (spline.numberOfFitPoints > 0) { return new AcDbSpline(spline.fitPoints, 'Uniform', spline.degree, !!(spline.flag & 0x01)); } } catch (error) { console.log("Failed to convert spline with error: ".concat(error)); } return null; }; AcDbEntityConverter.prototype.convertPoint = function (point) { var dbEntity = new AcDbPoint(); dbEntity.position = point.position; return dbEntity; }; AcDbEntityConverter.prototype.convertSolid = function (solid) { var dbEntity = new AcDbTrace(); dbEntity.setPointAt(0, __assign(__assign({}, solid.corner1), { z: 0 })); dbEntity.setPointAt(1, __assign(__assign({}, solid.corner2), { z: 0 })); dbEntity.setPointAt(2, __assign(__assign({}, solid.corner3), { z: 0 })); dbEntity.setPointAt(3, solid.corner4 ? __assign(__assign({}, solid.corner4), { z: 0 }) : __assign(__assign({}, solid.corner3), { z: 0 })); dbEntity.thickness = solid.thickness; return dbEntity; }; AcDbEntityConverter.prototype.convertLWPolyline = function (polyline) { var _a; // Libredwg changes meaning of the 'flag' field. '512' means closed. var dbEntity = new AcDbPolyline(); dbEntity.closed = !!(polyline.flag & 0x200); var defaultWidth = (_a = polyline.constantWidth) !== null && _a !== void 0 ? _a : -1; polyline.vertices.forEach(function (vertex, index) { var _a, _b; dbEntity.addVertexAt(index, new AcGePoint2d(vertex.x, vertex.y), vertex.bulge, (_a = vertex.startWidth) !== null && _a !== void 0 ? _a : defaultWidth, (_b = vertex.endWidth) !== null && _b !== void 0 ? _b : defaultWidth); }); return dbEntity; }; AcDbEntityConverter.prototype.convertPolyline2d = function (polyline) { var _a, _b; // Polyline flag (bit-coded; default = 0): // https://help.autodesk.com/view/OARX/2023/ENU/?guid=GUID-ABF6B778-BE20-4B49-9B58-A94E64CEFFF3 // // 1 = This is a closed polyline (or a polygon mesh closed in the M direction) // 2 = Curve-fit vertices have been added // 4 = Spline-fit vertices have been added // 8 = This is a 3D polyline // 16 = This is a 3D polygon mesh // 32 = The polygon mesh is closed in the N direction // 64 = The polyline is a polyface mesh // 128 = The linetype pattern is generated continuously around the vertices of this polyline var isClosed = !!(polyline.flag & 0x01); var isPolygonMesh = !!(polyline.flag & 0x10); // 16 var isPolyfaceMesh = !!(polyline.flag & 0x40); // 64 var isClosedN = !!(polyline.flag & 0x20); // 32 // Filter out spline control points var vertices = []; var bulges = []; var faces = []; polyline.vertices.map(function (vertex) { var _a, _b; // Check whether it is one spline control point if (!(vertex.flag & 0x10)) { // For polyface mesh, vertex flag 128 bit is set for all vertices if (isPolyfaceMesh && vertex.flag & 0x80) { // 128 bit set // Check if this is a face vertex (64 bit not set) if (!(vertex.flag & 0x40)) { // 64 bit not set // This is a face vertex var faceVertices = []; // If the index is negative, the edge that begins with that vertex is invisible. // The first 0 vertex marks the end of the vertices of the face. if (vertex.polyfaceIndex0 != null && vertex.polyfaceIndex0 != 0) faceVertices.push(Math.abs(vertex.polyfaceIndex0) - 1); if (vertex.polyfaceIndex1 != null && vertex.polyfaceIndex1 != 0) faceVertices.push(Math.abs(vertex.polyfaceIndex1) - 1); if (vertex.polyfaceIndex2 != null && vertex.polyfaceIndex2 != 0) faceVertices.push(Math.abs(vertex.polyfaceIndex2) - 1); if (vertex.polyfaceIndex3 != null && vertex.polyfaceIndex3 != 0) faceVertices.push(Math.abs(vertex.polyfaceIndex3) - 1); if (faceVertices.length >= 3) { faces.push(faceVertices); } } else { // This is a regular vertex (64 bit set) vertices.push({ x: vertex.x, y: vertex.y, z: vertex.z }); bulges.push((_a = vertex.bulge) !== null && _a !== void 0 ? _a : 0); } } else { // This is a regular vertex vertices.push({ x: vertex.x, y: vertex.y, z: vertex.z }); bulges.push((_b = vertex.bulge) !== null && _b !== void 0 ? _b : 0); } } }); if (isPolygonMesh) { // For polygon mesh, we need M and N counts // In DXF, these are stored in the polyline entity as 71 and 72 group codes var mCount = (_a = polyline.meshMVertexCount) !== null && _a !== void 0 ? _a : 2; var nCount = (_b = polyline.meshNVertexCount) !== null && _b !== void 0 ? _b : 2; return new AcDbPolygonMesh(mCount, nCount, vertices, isClosed, isClosedN); } else if (isPolyfaceMesh) { return new AcDbPolyFaceMesh(vertices, faces); } else { var polyType = AcDbPoly2dType.SimplePoly; if (polyline.flag & 0x02) { polyType = AcDbPoly2dType.FitCurvePoly; } else if (polyline.flag & 0x04) { // Please don't use enum DwgSmoothType value here. // It will result in libredwg-web bundled in this package. if (polyline.smoothType == 6) { // DwgSmoothType.CUBIC polyType = AcDbPoly2dType.CubicSplinePoly; } else if (polyline.smoothType == 5) { // DwgSmoothType.QUADRATIC polyType = AcDbPoly2dType.QuadSplinePoly; } } return new AcDb2dPolyline(polyType, vertices, 0, isClosed, polyline.startWidth, polyline.endWidth, bulges); } }; AcDbEntityConverter.prototype.convertPolyline3d = function (polyline) { // Polyline flag (bit-coded; default = 0): // https://help.autodesk.com/view/OARX/2023/ENU/?guid=GUID-ABF6B778-BE20-4B49-9B58-A94E64CEFFF3 // // 1 = This is a closed polyline (or a polygon mesh closed in the M direction) // 2 = Curve-fit vertices have been added // 4 = Spline-fit vertices have been added // 8 = This is a 3D polyline // 16 = This is a 3D polygon mesh // 32 = The polygon mesh is closed in the N direction // 64 = The polyline is a polyface mesh // 128 = The linetype pattern is generated continuously around the vertices of this polyline var isClosed = !!(polyline.flag & 0x01); // Filter out spline control points var vertices = []; polyline.vertices.map(function (vertex) { // Check whether it is one spline control point if (!(vertex.flag & 0x10)) { vertices.push({ x: vertex.x, y: vertex.y, z: vertex.z }); } }); var polyType = AcDbPoly3dType.SimplePoly; if (polyline.flag & 0x04) { // Please don't use enum DwgSmoothType value here. // It will result in libredwg-web bundled in this package. if (polyline.smoothType == 6) { // DwgSmoothType.CUBIC polyType = AcDbPoly3dType.CubicSplinePoly; } else if (polyline.smoothType == 5) { // DwgSmoothType.QUADRATIC polyType = AcDbPoly3dType.QuadSplinePoly; } } return new AcDb3dPolyline(polyType, vertices, isClosed); }; AcDbEntityConverter.prototype.convertHatch = function (hatch) { var _a, _b, _c, _d; var dbEntity = new AcDbHatch(); (_a = hatch.definitionLines) === null || _a === void 0 ? void 0 : _a.forEach(function (item) { dbEntity.definitionLines.push({ angle: item.angle, base: item.base, offset: item.offset, dashLengths: item.numberOfDashLengths > 0 ? item.dashLengths : [] }); }); // Important: Don't use DwgHatchSolidFill.SolidFill to avoid bundling libredwg-web into libredeg-converter dbEntity.isSolidFill = hatch.solidFill == 1; dbEntity.hatchStyle = hatch.hatchStyle; dbEntity.patternName = hatch.patternName; dbEntity.patternType = hatch.patternType; dbEntity.patternAngle = hatch.patternAngle == null ? 0 : hatch.patternAngle; dbEntity.patternScale = hatch.patternScale == null ? 0 : hatch.patternScale; var paths = hatch.boundaryPaths; paths.forEach(function (path) { var flag = path.boundaryPathTypeFlag; // Check whether it is a polyline if (flag & 0x02) { var polylinePath = path; var polyline_1 = new AcGePolyline2d(); polyline_1.closed = polylinePath.isClosed; polylinePath.vertices.forEach(function (vertex, index) { polyline_1.addVertexAt(index, { x: vertex.x, y: vertex.y, bulge: vertex.bulge }); }); dbEntity.add(polyline_1); } else { var edgePath = path; var edges_1 = []; edgePath.edges.forEach(function (edge) { // TODO: It seems there are some issue on libredwg. Sometimes 'undefined' edges are added. if (edge == null) return; if (edge.type == 1) { var line = edge; edges_1.push(new AcGeLine2d(line.start, line.end)); } else if (edge.type == 2) { var arc = edge; edges_1.push(new AcGeCircArc2d(arc.center, arc.radius, arc.startAngle, arc.endAngle, !arc.isCCW)); } else if (edge.type == 3) { var ellipse = edge; var majorAxis = new AcGeVector2d(); majorAxis.subVectors(ellipse.end, ellipse.center); var majorAxisRadius = Math.sqrt(Math.pow(ellipse.end.x, 2) + Math.pow(ellipse.end.y, 2)); // Property name 'lengthOfMinorAxis' is really confusing. // Actually length of minor axis means percentage of major axis length. var minorAxisRadius = majorAxisRadius * ellipse.lengthOfMinorAxis; var startAngle = ellipse.startAngle; var endAngle = ellipse.endAngle; var rotation = Math.atan2(ellipse.end.y, ellipse.end.x); if (!ellipse.isCCW) { // when clockwise, need to handle start/end angles startAngle = Math.PI * 2 - startAngle; endAngle = Math.PI * 2 - endAngle; } edges_1.push(new AcGeEllipseArc2d(__assign(__assign({}, ellipse.center), { z: 0 }), majorAxisRadius, minorAxisRadius, startAngle, endAngle, !ellipse.isCCW, rotation)); } else if (edge.type == 4) { var spline = edge; if (spline.numberOfControlPoints > 0 && spline.numberOfKnots > 0) { var controlPoints = spline.controlPoints.map(function (item) { return { x: item.x, y: item.y, z: 0 }; }); var hasWeights_1 = true; var weights = spline.controlPoints.map(function (item) { if (item.weight == null) hasWeights_1 = false; return item.weight || 1; }); edges_1.push(new AcGeSpline3d(controlPoints, spline.knots, hasWeights_1 ? weights : undefined)); } else if (spline.numberOfFitData > 0) { var fitPoints = spline.fitDatum.map(function (item) { return { x: item.x, y: item.y, z: 0 }; }); edges_1.push(new AcGeSpline3d(fitPoints, 'Uniform')); } } }); var loops = AcGeLoop2d.buildFromEdges(edges_1); if (loops.length == 0 && edges_1.length > 0) { // Fallback: keep original order if we failed to build any loop. dbEntity.add(new AcGeLoop2d(edges_1)); } else { loops.forEach(function (loop) { return dbEntity.add(loop); }); } } }); // Handle gradient fill properties // The meaning of gradientFlag is as follows. // - 0: Solid hatch // - 1: Gradient if (hatch.gradientFlag) { var gradientHatch = hatch; dbEntity.hatchObjectType = AcDbHatchObjectType.GradientObject; dbEntity.gradientName = gradientHatch.gradientName; dbEntity.gradientAngle = (_b = gradientHatch.gradientRotation) !== null && _b !== void 0 ? _b : 0; dbEntity.gradientShift = (_c = gradientHatch.gradientDefinition) !== null && _c !== void 0 ? _c : 0; dbEntity.gradientOneColorMode = gradientHatch.gradientColorFlag == 1; dbEntity.shadeTintValue = (_d = gradientHatch.colorTint) !== null && _d !== void 0 ? _d : 0; if (gradientHatch.gradientColors) { var length_1 = gradientHatch.gradientColors.length; if (length_1 > 1) { dbEntity.gradientStartColor = gradientHatch.gradientColors[0].rgb; dbEntity.gradientEndColor = gradientHatch.gradientColors[1].rgb; } else if (length_1 > 0) { dbEntity.gradientStartColor = gradientHatch.gradientColors[0].rgb; } } } return dbEntity; }; AcDbEntityConverter.prototype.convertTable = function (table) { var dbEntity = new AcDbTable(table.name, table.rowCount, table.columnCount); // dbEntity.tableDataVersion = table.version dbEntity.tableStyleId = table.tableStyleId; dbEntity.owningBlockRecordId = table.blockRecordHandle; if (table.directionVector) { dbEntity.horizontalDirection = new AcGeVector3d(table.directionVector); } dbEntity.attachmentPoint = table.attachmentPoint; dbEntity.position.copy(table.startPoint); dbEntity.tableValueFlag = table.tableValue; dbEntity.tableOverrideFlag = table.overrideFlag; dbEntity.borderColorOverrideFlag = table.borderColorOverrideFlag; dbEntity.borderLineweightOverrideFlag = table.borderLineWeightOverrideFlag; dbEntity.borderVisibilityOverrideFlag = table.borderVisibilityOverrideFlag; table.columnWidthArr.forEach(function (width, index) { return dbEntity.setColumnWidth(index, width); }); table.rowHeightArr.forEach(function (height, index) { return dbEntity.setRowHeight(index, height); }); table.cells.forEach(function (cell, index) { dbEntity.setCell(index, cell); }); return dbEntity; }; AcDbEntityConverter.prototype.convertText = function (text) { var _a, _b, _c; var dbEntity = new AcDbText(); dbEntity.textString = text.text; dbEntity.styleName = text.styleName; dbEntity.height = text.textHeight; dbEntity.position.copy(text.startPoint); // Propagate DXF group 11 (alignment point) so non-default justifications // place the text correctly. `endPoint` is libredwg's name for the // alignment point on a TEXT entity. Fall back to startPoint when group // 11 is missing or surfaces as the zero point — see comment in // `convertAttributeCommon`. var isEndPointZero = !text.endPoint || (text.endPoint.x === 0 && text.endPoint.y === 0 && ((_a = text.endPoint.z) !== null && _a !== void 0 ? _a : 0) === 0); if (text.endPoint && !isEndPointZero) { dbEntity.alignmentPoint.copy(text.endPoint); } else { dbEntity.alignmentPoint.copy(text.startPoint); } dbEntity.rotation = text.rotation; dbEntity.oblique = (_b = text.obliqueAngle) !== null && _b !== void 0 ? _b : 0; dbEntity.thickness = text.thickness; dbEntity.horizontalMode = text.halign; dbEntity.verticalMode = text.valign; dbEntity.widthFactor = (_c = text.xScale) !== null && _c !== void 0 ? _c : 1; return dbEntity; }; AcDbEntityConverter.prototype.convertMText = function (mtext) { var dbEntity = new AcDbMText(); dbEntity.contents = mtext.text; if (mtext.styleName != null) { dbEntity.styleName = mtext.styleName; } dbEntity.height = mtext.textHeight; dbEntity.width = mtext.rectWidth; dbEntity.rotation = mtext.rotation || 0; dbEntity.location = mtext.insertionPoint; dbEntity.attachmentPoint = mtext.attachmentPoint; if (mtext.direction) { dbEntity.direction = new AcGeVector3d(mtext.direction); } dbEntity.drawingDirection = mtext.drawingDirection; return dbEntity; }; AcDbEntityConverter.prototype.convertLeader = function (leader) { var dbEntity = new AcDbLeader(); leader.vertices.forEach(function (point) { dbEntity.appendVertex(point); }); dbEntity.hasArrowHead = leader.isArrowheadEnabled; dbEntity.hasHookLine = leader.isHooklineExists; dbEntity.isSplined = leader.isSpline; dbEntity.dimensionStyle = leader.styleName; dbEntity.annoType = leader.leaderCreationFlag; return dbEntity; }; AcDbEntityConverter.prototype.convertMLine = function (mline) { var _a, _b, _c; var dbEntity = new AcDbMLine(); dbEntity.styleName = mline.mlineStyle || 'STANDARD'; dbEntity.scale = mline.scale; dbEntity.flags = mline.flags; dbEntity.justification = mline.justification; dbEntity.startPosition = mline.startPoint; dbEntity.normal = (_a = mline.extrusionDirection) !== null && _a !== void 0 ? _a : AcGeVector3d.Z_AXIS; dbEntity.styleCount = (_b = mline.numberOfLines) !== null && _b !== void 0 ? _b : 0; dbEntity.segments = ((_c = mline.vertices) !== null && _c !== void 0 ? _c : []).map(function (vertex) { var _a; return ({ position: vertex.vertex, direction: vertex.vertexDirection, miterDirection: vertex.miterDirection, elements: ((_a = vertex.lines) !== null && _a !== void 0 ? _a : []).map(function (line) { var _a, _b; return ({ parameterCount: line.numberOfSegmentParams, parameters: (_a = line.segmentParams) !== null && _a !== void 0 ? _a : [], fillCount: line.numberOfAreaFillParams, fillParameters: (_b = line.areaFillParams) !== null && _b !== void 0 ? _b : [] }); }) }); }); return dbEntity; }; AcDbEntityConverter.prototype.convertMLeader = function (mleader) { var _a, _b, _c, _d, _e, _f, _g, _h, _j, _k, _l, _m, _o, _p; var dbEntity = new AcDbMLeader(); var raw = mleader; dbEntity.leaderLineType = ((_a = this.readNumber(raw, [ 'multileaderType', 'leaderLineType', 'leaderType' ])) !== null && _a !== void 0 ? _a : AcDbMLeaderLineType.StraightLeader); var contentType = (_b = this.readNumber(raw, ['contentType'])) !== null && _b !== void 0 ? _b : (mleader.textContent ? AcDbMLeaderContentType.MTextContent : mleader.blockContent ? AcDbMLeaderContentType.BlockContent : AcDbMLeaderContentType.NoneContent); dbEntity.contentType = contentType; dbEntity.doglegEnabled = (_c = this.readBoolean(raw, ['doglegEnabled', 'enableDogleg'])) !== null && _c !== void 0 ? _c : false; dbEntity.doglegLength = (_d = this.readNumber(raw, ['doglegLength'])) !== null && _d !== void 0 ? _d : 0; if (mleader.landingPoint) dbEntity.landingPoint = mleader.landingPoint; if (mleader.doglegVector) dbEntity.doglegVector = mleader.doglegVector; var styleId = this.readString(raw, [ 'mleaderStyleId', 'mLeaderStyleId', 'mleaderStyleHandle', 'styleHandle', 'styleName' ]); if (styleId) dbEntity.mleaderStyleId = styleId; var normal = this.readPoint(raw, ['normal', 'extrusionDirection']); if (normal) dbEntity.normal = normal; var textContent = mleader.textContent; var textStyleName = (_e = this.readString(textContent !== null && textContent !== void 0 ? textContent : {}, ['styleName', 'textStyleName'])) !== null && _e !== void 0 ? _e : this.readString(raw, ['textStyleName', 'textStyle', 'styleName']); if (textStyleName) dbEntity.textStyleName = textStyleName; dbEntity.textHeight = (_g = (_f = this.readNumber(textContent !== null && textContent !== void 0 ? textContent : {}, ['textHeight', 'height'])) !== null && _f !== void 0 ? _f : this.readNumber(raw, [ 'textHeight', 'mtextHeight', 'textContentHeight' ])) !== null && _g !== void 0 ? _g : dbEntity.textHeight; dbEntity.textWidth = (_j = (_h = this.readNumber(textContent !== null && textContent !== void 0 ? textContent : {}, ['textWidth', 'width'])) !== null && _h !== void 0 ? _h : this.readNumber(raw, ['textWidth', 'mtextWidth', 'textContentWidth'])) !== null && _j !== void 0 ? _j : dbEntity.textWidth; var textRotation = (_k = this.readNumber(textContent !== null && textContent !== void 0 ? textContent : {}, ['textRotation', 'rotation'])) !== null && _k !== void 0 ? _k : this.readNumber(raw, [ 'textRotation', 'mtextRotation', 'textContentRotation' ]); if (textRotation != null) dbEntity.textRotation = textRotation; var textDirection = this.readPoint(raw, [ 'textDirection', 'mtextDirection', 'textDirectionVector' ]); if (textDirection) dbEntity.textDirection = textDirection; var textAttachmentPoint = this.readNumber(raw, [ 'textAttachmentPoint', 'attachmentPoint' ]); if (textAttachmentPoint != null) { dbEntity.textAttachmentPoint = textAttachmentPoint; } var textDrawingDirection = this.readNumber(raw, [ 'textDrawingDirection', 'drawingDirection' ]); if (textDrawingDirection != null) { dbEntity.textDrawingDirection = textDrawingDirection; } if (((_l = mleader.textContent) === null || _l === void 0 ? void 0 : _l.text) != null && mleader.textContent.anchorPoint) { dbEntity.mtextContent = { text: mleader.textContent.text, anchorPoint: mleader.textContent.anchorPoint }; } else { var text = this.readString(raw, ['text', 'contents', 'mtext']); var anchorPoint = this.readPoint(raw, [ 'textLocation', 'textPosition', 'textAnchorPoint' ]); if (text != null && anchorPoint) { dbEntity.mtextContent = { text: text, anchorPoint: anchorPoint }; } } if (((_m = mleader.blockContent) === null || _m === void 0 ? void 0 : _m.blockHandle) && mleader.blockContent.position) { dbEntity.blockContent = { blockHandle: mleader.blockContent.blockHandle, position: mleader.blockContent.position }; } else { var blockHandle = this.readString(raw, [ 'blockHandle', 'blockContentHandle', 'blockId' ]); var blockPosition = this.readPoint(raw, [ 'blockPosition', 'blockContentPosition' ]); if (blockHandle && blockPosition) { dbEntity.blockContent = { blockHandle: blockHandle, position: blockPosition }; } } (_o = mleader.leaders) === null || _o === void 0 ? void 0 : _o.forEach(function (leader) { var _a, _b, _c, _d; var leaderIndex = dbEntity.addLeader({ landingPoint: (_a = leader.landingPoint) !== null && _a !== void 0 ? _a : mleader.landingPoint, doglegVector: (_b = leader.doglegVector) !== null && _b !== void 0 ? _b : mleader.doglegVector, doglegLength: (_c = leader.doglegLength) !== null && _c !== void 0 ? _c : mleader.doglegLength }); (_d = leader.leaderLines) === null || _d === void 0 ? void 0 : _d.forEach(function (line) { var _a, _b; var lineIndex = dbEntity.addLeaderLine(leaderIndex, (_a = line.vertices) !== null && _a !== void 0 ? _a : []); (_b = line.breaks) === null || _b === void 0 ? void 0 : _b.forEach(function (item) { dbEntity.addBreak(leaderIndex, lineIndex, item.start, item.end); }); }); }); if (dbEntity.numberOfLeaders === 0) { (_p = this.readLeaderLineArray(raw)) === null || _p === void 0 ? void 0 : _p.forEach(function (line) { var leaderIndex = dbEntity.addLeader({ landingPoint: mleader.landingPoint, doglegVector: mleader.doglegVector, doglegLength: mleader.doglegLength }); dbEntity.addLeaderLine(leaderIndex, line); }); } return dbEntity; }; AcDbEntityConverter.prototype.convertDimension = function (dimension) { if (dimension.subclassMarker == 'AcDbAlignedDimension') { var entity = dimension; var dbEntity = new AcDbAlignedDimension(entity.subDefinitionPoint1, entity.subDefinitionPoint2, entity.definitionPoint); if (entity.insertionPoint) { dbEntity.dimBlockPosition = { x: entity.insertionPoint.x, y: entity.insertionPoint.y, z: 0 }; } dbEntity.rotation = entity.rotationAngle; this.processDimensionCommonAttrs(dimension, dbEntity); return dbEntity; } else if (dimension.subclassMarker == 'AcDbRotatedDimension') { var entity = dimension; var dbEntity = new AcDbRotatedDimension(entity.subDefinitionPoint1, entity.subDefinitionPoint2, entity.definitionPoint); if (entity.insertionPoint) { dbEntity.dimBlockPosition = { x: entity.insertionPoint.x, y: entity.insertionPoint.y, z: 0 }; } dbEntity.rotation = entity.rotationAngle; this.processDimensionCommonAttrs(dimension, dbEntity); return dbEntity; } else if (dimension.subclassMarker == 'AcDb3PointAngularDimension') { var entity = dimension; var dbEntity = new AcDb3PointAngularDimension(entity.centerPoint, entity.subDefinitionPoint1, entity.subDefinitionPoint2, entity.definitionPoint); this.processDimensionCommonAttrs(dimension, dbEntity); return dbEntity; } else if (dimension.subclassMarker == 'AcDbOrdinateDimension') { var entity = dimension; var dbEntity = new AcDbOrdinateDimension(entity.subDefinitionPoint1, entity.subDefinitionPoint2); this.processDimensionCommonAttrs(dimension, dbEntity); return dbEntity; } else if (dimension.subclassMarker == 'AcDbRadialDimension') { var entity = dimension; var dbEntity = new AcDbRadialDimension(entity.definitionPoint, entity.centerPoint, entity.leaderLength); this.processDimensionCommonAttrs(dimension, dbEntity); return dbEntity; } else if (dimension.subclassMarker == 'AcDbDiametricDimension') { var entity = dimension; var dbEntity = new AcDbDiametricDimension(entity.definitionPoint, entity.centerPoint, entity.leaderLength); this.processDimensionCommonAttrs(dimension, dbEntity); return dbEntity; } return null; }; AcDbEntityConverter.prototype.processImage = function (image, dbImage) { dbImage.position.copy(image.position); dbImage.brightness = image.brightness; dbImage.contrast = image.contrast; dbImage.fade = image.fade; dbImage.imageSize.copy(image.imageSize); dbImage.imageDefId = image.imageDefHandle; dbImage.isClipped = image.clipping > 0; dbImage.isShownClipped = (image.flags | 0x0004) > 0; dbImage.isImageShown = (image.flags | 0x0003) > 0; dbImage.isImageTransparent = (image.flags | 0x0008) > 0; image.clippingBoundaryPath.forEach(function (point) { dbImage.clipBoundary.push(new AcGePoint2d(point)); }); dbImage.clipBoundaryType = image.clippingBoundaryType; // Calculate the scale factors dbImage.width = Math.sqrt(Math.pow(image.uPixel.x, 2) + Math.pow(image.uPixel.y, 2) + Math.pow(image.uPixel.z, 2)) * image.imageSize.x; dbImage.height = Math.sqrt(Math.pow(image.vPixel.x, 2) + Math.pow(image.vPixel.y, 2) + Math.pow(image.vPixel.z, 2)) * image.imageSize.y; // Calculate the rotation angle // Rotation is determined by the angle of the U-vector relative to the X-axis dbImage.rotation = Math.atan2(image.uPixel.y, image.uPixel.x); }; AcDbEntityConverter.prototype.convertImage = function (image) { var dbImage = new AcDbRasterImage(); this.processImage(image, dbImage); return dbImage; }; AcDbEntityConverter.prototype.convertWipeout = function (wipeout) { var dbWipeout = new AcDbWipeout(); this.processImage(wipeout, dbWipeout); return dbWipeout; }; AcDbEntityConverter.prototype.convertViewport = function (viewport) { var dbViewport = new AcDbViewport(); dbViewport.number = viewport.viewportId; dbViewport.centerPoint.copy(viewport.viewportCenter); dbViewport.height = viewport.height; dbViewport.width = viewport.width; dbViewport.viewCenter.copy(viewport.displayCenter); dbViewport.viewHeight = viewport.viewHeight; return dbViewport; }; AcDbEntityConverter.prototype.convertRay = function (ray) { var dbRay = new AcDbRay(); dbRay.basePoint.copy(ray.firstPoint); dbRay.unitDir.copy(ray.unitDirection); return dbRay; }; AcDbEntityConverter.prototype.convertXline = function (xline) { var dbXline = new AcDbXline(); dbXline.basePoint.copy(xline.firstPoint); dbXline.unitDir.copy(xline.unitDirection); return dbXline; }; AcDbEntityConverter.prototype.convertAttributeCommon = function (attrib, dbAttrib) { var _a, _b, _c, _d; var text = attrib.text; dbAttrib.textString = text.text; dbAttrib.styleName = text.styleName; dbAttrib.height = text.textHeight; dbAttrib.position.copy(text.startPoint); // Propagate the alignment point (DXF group 11). It is meaningful only // when halign/valign deviate from Left/Baseline, but we always copy it // so DXF round-trip preserves the original value. Prefer the dedicated // field on the parent entity (3D for ATTRIB, 2D for ATTDEF); fall back // to the embedded text's `endPoint` which carries the same information. // libredwg sometimes surfaces a zero point for entities that simply // omit group 11 in the source DWG — fall back to startPoint so the // alignment anchor never collapses to the world origin and is always // moved consistently with the position by `transformBy`. var alignmentPoint = (_a = attrib.alignmentPoint) !== null && _a !== void 0 ? _a : text.endPoint; var isAlignmentPointZero = !alignmentPoint || (alignmentPoint.x === 0 && alignmentPoint.y === 0 && ((_b = alignmentPoint.z) !== null && _b !== void 0 ? _b : 0) === 0); if (alignmentPoint && !isAlignmentPointZero) { dbAttrib.alignmentPoint.copy(alignmentPoint); } else { dbAttrib.alignmentPoint.copy(text.startPoint); } dbAttrib.rotation = text.rotation; dbAttrib.oblique = (_c = text.obliqueAngle) !== null && _c !== void 0 ? _c : 0; dbAttrib.thickness = text.thickness; dbAttrib.horizontalMode = text.halign; dbAttrib.verticalMode = text.valign; dbAttrib.widthFactor = (_d = text.xScale) !== null && _d !== void 0 ? _d : 1; dbAttrib.tag = attrib.tag; dbAttrib.fieldLength = attrib.fieldLength; dbAttrib.isInvisible = (attrib.flags & AcDbAttributeFlags.Invisible) !== 0; dbAttrib.isConst = (attrib.flags & AcDbAttributeFlags.Const) !== 0; dbAttrib.isVerifiable = (attrib.flags & AcDbAttributeFlags.Verifiable) !== 0; dbAttrib.isPreset = (attrib.flags & AcDbAttributeFlags.Preset) !== 0; dbAttrib.lockPositionInBlock = attrib.lockPositionFlag; dbAttrib.isReallyLocked = attrib.isReallyLocked; dbAttrib.isMTextAttribute = (attrib.mtextFlag & AcDbAttributeMTextFlag.MultiLine) !== 0; dbAttrib.isConstMTextAttribute = (attrib.mtextFlag & AcDbAttributeMTextFlag.ConstMultiLine) !== 0; }; AcDbEntityConverter.prototype.convertAttribute = function (attrib) { var dbAttrib = new AcDbAttribute(); this.convertAttributeCommon(attrib, dbAttrib); return dbAttrib; }; AcDbEntityConverter.prototype.convertAttributeDefinition = function (attrib) { var dbAttDef = new AcDbAttributeDefinition(); this.convertAttributeCommon(attrib, dbAttDef); dbAttDef.prompt = attrib.prompt; return dbAttDef; }; AcDbEntityConverter.prototype.convertBlockReference = function (blockReference) { var _this = this; var dbBlockReference = new AcDbBlockReference(blockReference.name); if (blockReference.insertionPoint) dbBlockReference.position.copy(blockReference.insertionPoint); dbBlockReference.scaleFactors.x = blockReference.xScale; dbBlockReference.scaleFactors.y = blockReference.yScale; dbBlockReference.scaleFactors.z = blockReference.zScale; dbBlockReference.rotation = blockReference.rotation; dbBlockReference.normal.copy(blockReference.extrusionDirection); // Pre-assign the BlockReference's objectId from the DWG handle so that // `appendAttributes` below (which sets `attrib.ownerId = this.objectId`) // produces a valid ownerId pointing at this INSERT, matching ObjectARX // semantics. Without this, ownerId would be assigned undefined here and // only later when `processCommonAttrs` runs on the returned BlockReference. if (blockReference.handle != null) { dbBlockReference.objectId = blockReference.handle; } if (blockReference.attribs) { blockReference.attribs.forEach(function (attrib) { // Route through `convert()` rather than `convertAttribute()` so // `processCommonAttrs` runs and the AcDbAttribute receives its // layer / color / objectId / lineType / lineWeight / linetypeScale // from the DWG. Without this, ATTRIBs render with default styling // and cannot be addressed individually by per-layer toggles. var dbAttrib = _this.convert(attrib); if (dbAttrib instanceof AcDbAttribute) { dbBlockReference.appendAttributes(dbAttrib); } }); } return dbBlockReference; }; AcDbEntityConverter.prototype.processDimensionCommonAttrs = function (entity, dbEntity) { dbEntity.dimBlockId = entity.name; dbEntity.textPosition.copy(entity.textPoint); dbEntity.textRotation = entity.textRotation || 0; if (entity.textLineSpacingFactor) { dbEntity.textLineSpacingFactor = entity.textLineSpacingFactor; } if (entity.textLineSpacingStyle) { dbEntity.textLineSpacingStyle = entity.textLineSpacingStyle; } dbEntity.dimensionStyleName = entity.styleName; dbEntity.dimensionText = entity.text || ''; dbEntity.measurement = entity.measurement; }; AcDbEntityConverter.prototype.processCommonAttrs = function (entity, dbEntity) { dbEntity.layer = entity.layer || '0'; dbEntity.objectId = entity.handle; if (entity.ownerBlockRecordSoftId != null) { dbEntity.ownerId = entity.ownerBlockRecordSoftId; } if (entity.lineType != null) { dbEntity.lineType = entity.lineType; } if (entity.lineweight != null) { dbEntity.lineWeight = entity.lineweight; } if (entity.lineTypeScale != null) { dbEntity.linetypeScale = entity.lineTypeScale; } // Build the entity color in a fresh AcCmColor and assign it via the // setter. The previous pattern (`dbEntity.color.<prop> = …`) read the // getter and mutated the result, which works for entities whose getter // returns the cached `_color` field but breaks for entities like // AcDbHatch that override the getter to return a clone of an HPCOLOR / // CECOLOR fallback (PR #78). Mutations on a clone are dropped, leaving // the entity stuck on the sysvar default and losing the DWG's RGB. if (entity.color != null || entity.colorIndex != null || entity.colorName) { var color = new AcCmColor(); if (entity.color != null) { color.setRGBValue(entity.color); } if (entity.colorIndex != null) { // ACI color precedence rule: // - If the libredwg binding already resolved a concrete RGB for // the entity (entity.color != null), that RGB reflects the // DWG's own color table — trust it and do NOT overwrite with // ACI resolution from our default palette (which loses custom // palette mappings, e.g. ACI 254 → #d8f5c2 in the source DWG // vs. near-black in our default palette). // - Exception: colorIndex === 7 is semantically special (the // "foreground" color that flips with COLORTHEME). Preserve it // as ByACI(7) so that AcCmColor.isForeground stays true and // text keeps inverting with the theme. if (entity.color == null || entity.colorIndex === 7) { color.colorIndex = entity.colorIndex; } } if (entity.colorName) { color.colorName = entity.colorName; } dbEntity.color = color; } if (entity.isVisible != null) { dbEntity.visibility = entity.isVisible; } if (entity.transparency != null) { var transparency = new AcCmTransparency(); transparency.method = entity.transparencyType; if (transparency.isByBlock || transparency.isByBlock) { transparency.alpha = entity.transparency; } dbEntity.transparency = transparency; } }; AcDbEntityConverter.prototype.readNumber = function (source, names) { var e_1, _a; try {