@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
JavaScript
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 {