第十四章:文件格式与数据交换
14.1 文件格式支持概述
14.1.1 LightCAD支持的格式
| 格式 | 读取 | 写入 | 说明 |
|---|---|---|---|
| LightCAD原生格式 | ✅ | ✅ | 完整保留所有数据 |
| DWG | ✅ | ✅ | AutoCAD绘图格式(通过ODA SDK) |
| DXF | ✅ | ✅ | AutoCAD交换格式(通过netDxf) |
| SketchUp (.skp) | ✅ | ✅ | SketchUp模型格式 |
| SVG | ✅ | - | 可缩放矢量图形 |
14.1.2 模块结构
LightCAD.ImportAndExport/
├── DwgImporter.cs # DWG导入
├── DwgExporter.cs # DWG导出
├── DxfImporter.cs # DXF导入
├── DxfExporter.cs # DXF导出
├── SketchUpImporter.cs # SketchUp导入
├── SketchUpExporter.cs # SketchUp导出
└── FormatConverter.cs # 格式转换器
src/Libs/
├── LightCAD.DwgReaderWrite/ # DWG读写库
└── ODA SDK DLLs # Open Design Alliance SDK
src/netDxf/ # DXF处理库(源码)
├── DxfDocument.cs # DXF文档
├── DxfReader.cs # DXF读取器
├── DxfWriter.cs # DXF写入器
└── Entities/ # DXF实体映射
14.2 DWG格式支持
14.2.1 DWG格式概述
DWG(Drawing)是AutoCAD的原生文件格式,也是CAD行业最广泛使用的文件格式。LightCAD通过ODA(Open Design Alliance)SDK实现了对DWG格式的读写支持。
14.2.2 DWG导入
public class DwgImporter
{
/// <summary>
/// 导入DWG文件
/// </summary>
public LcDocument Import(string filePath)
{
var document = new LcDocument();
using (var database = new OdDatabase())
{
// 读取DWG文件
database.ReadDwgFile(filePath);
// 导入图层
ImportLayers(database, document);
// 导入线型
ImportLineTypes(database, document);
// 导入文字样式
ImportTextStyles(database, document);
// 导入标注样式
ImportDimStyles(database, document);
// 导入块定义
ImportBlocks(database, document);
// 导入模型空间中的实体
ImportEntities(database, document);
}
return document;
}
/// <summary>
/// 导入图层
/// </summary>
private void ImportLayers(OdDatabase database, LcDocument document)
{
var layerTable = database.LayerTable;
foreach (var layerId in layerTable)
{
var layer = layerId.GetObject() as OdLayerTableRecord;
if (layer != null)
{
document.Layers.Create(layer.Name);
var lcLayer = document.Layers.Get(layer.Name);
lcLayer.Color = ConvertColor(layer.Color);
lcLayer.IsVisible = !layer.IsFrozen && !layer.IsOff;
lcLayer.IsLocked = layer.IsLocked;
lcLayer.LineType = layer.LinetypeName;
}
}
}
/// <summary>
/// 导入实体
/// </summary>
private void ImportEntities(OdDatabase database, LcDocument document)
{
var modelSpace = database.ModelSpace;
foreach (var entityId in modelSpace)
{
var entity = entityId.GetObject();
var lcEntity = ConvertEntity(entity);
if (lcEntity != null)
{
lcEntity.LayerName = entity.Layer;
lcEntity.Color = ConvertColor(entity.Color);
document.Entities.Add(lcEntity);
}
}
}
/// <summary>
/// 转换DWG实体为LightCAD实体
/// </summary>
private LcEntity ConvertEntity(OdEntity odEntity)
{
return odEntity switch
{
OdLine line => new LcLine
{
StartPoint = ConvertPoint(line.StartPoint),
EndPoint = ConvertPoint(line.EndPoint)
},
OdCircle circle => new LcCircle
{
Center = ConvertPoint(circle.Center).ToPoint2d(),
Radius = circle.Radius
},
OdArc arc => new LcArc
{
Center = ConvertPoint(arc.Center).ToPoint2d(),
Radius = arc.Radius,
StartAngle = arc.StartAngle,
EndAngle = arc.EndAngle
},
OdPolyline polyline => ConvertPolyline(polyline),
OdText text => ConvertText(text),
OdDimension dim => ConvertDimension(dim),
OdBlockReference blockRef => ConvertBlockReference(blockRef),
_ => null
};
}
}
14.2.3 DWG导出
public class DwgExporter
{
/// <summary>
/// 导出为DWG文件
/// </summary>
public void Export(LcDocument document, string filePath,
DwgVersion version = DwgVersion.AC1032)
{
using (var database = new OdDatabase())
{
// 设置DWG版本
database.DwgFileVersion = version;
// 导出图层
ExportLayers(document, database);
// 导出实体
ExportEntities(document, database);
// 导出块定义
ExportBlocks(document, database);
// 写入文件
database.SaveAs(filePath, version);
}
}
/// <summary>
/// 转换LightCAD实体为DWG实体
/// </summary>
private OdEntity ConvertToOdEntity(LcEntity entity)
{
return entity switch
{
LcLine line => new OdLine
{
StartPoint = ConvertToOdPoint(line.StartPoint),
EndPoint = ConvertToOdPoint(line.EndPoint)
},
LcCircle circle => new OdCircle
{
Center = ConvertToOdPoint3d(circle.Center),
Radius = circle.Radius
},
LcArc arc => new OdArc
{
Center = ConvertToOdPoint3d(arc.Center),
Radius = arc.Radius,
StartAngle = arc.StartAngle,
EndAngle = arc.EndAngle
},
_ => null
};
}
}
public enum DwgVersion
{
AC1015, // AutoCAD 2000
AC1018, // AutoCAD 2004
AC1021, // AutoCAD 2007
AC1024, // AutoCAD 2010
AC1027, // AutoCAD 2013
AC1032 // AutoCAD 2018+
}
14.3 DXF格式支持
14.3.1 DXF格式概述
DXF(Drawing Exchange Format)是AutoCAD的文本交换格式。相比DWG,DXF是开放的文本格式,更容易解析和生成。LightCAD使用netDxf库来处理DXF文件。
14.3.2 DXF导入
public class DxfImporter
{
/// <summary>
/// 导入DXF文件
/// </summary>
public LcDocument Import(string filePath)
{
var dxfDoc = netDxf.DxfDocument.Load(filePath);
var document = new LcDocument();
// 导入图层
foreach (var layer in dxfDoc.Layers)
{
var lcLayer = document.Layers.Create(layer.Name);
lcLayer.Color = ConvertDxfColor(layer.Color);
lcLayer.IsVisible = layer.IsVisible;
}
// 导入实体
ImportLines(dxfDoc, document);
ImportCircles(dxfDoc, document);
ImportArcs(dxfDoc, document);
ImportPolylines(dxfDoc, document);
ImportTexts(dxfDoc, document);
ImportDimensions(dxfDoc, document);
ImportInserts(dxfDoc, document);
return document;
}
private void ImportLines(netDxf.DxfDocument dxfDoc, LcDocument document)
{
foreach (var dxfLine in dxfDoc.Entities.Lines)
{
var line = new LcLine
{
StartPoint = new Point2d(
dxfLine.StartPoint.X, dxfLine.StartPoint.Y),
EndPoint = new Point2d(
dxfLine.EndPoint.X, dxfLine.EndPoint.Y),
LayerName = dxfLine.Layer.Name,
Color = ConvertDxfColor(dxfLine.Color)
};
document.Entities.Add(line);
}
}
private void ImportPolylines(netDxf.DxfDocument dxfDoc,
LcDocument document)
{
foreach (var dxfPoly in dxfDoc.Entities.LightWeightPolylines)
{
var polyline = new LcPolyline
{
IsClosed = dxfPoly.IsClosed,
LayerName = dxfPoly.Layer.Name
};
foreach (var vertex in dxfPoly.Vertexes)
{
polyline.AddVertex(
new Point2d(vertex.Position.X, vertex.Position.Y),
vertex.Bulge);
}
document.Entities.Add(polyline);
}
}
}
14.3.3 DXF导出
public class DxfExporter
{
/// <summary>
/// 导出为DXF文件
/// </summary>
public void Export(LcDocument document, string filePath,
DxfVersion version = DxfVersion.AutoCad2018)
{
var dxfDoc = new netDxf.DxfDocument(
(netDxf.Header.DxfVersion)version);
// 导出图层
foreach (var layerName in document.Layers.AllLayerNames)
{
var lcLayer = document.Layers.Get(layerName);
var dxfLayer = new netDxf.Tables.Layer(layerName)
{
Color = ConvertToAciColor(lcLayer.Color),
IsVisible = lcLayer.IsVisible
};
dxfDoc.Layers.Add(dxfLayer);
}
// 导出实体
foreach (var entity in document.Entities)
{
var dxfEntity = ConvertToDxfEntity(entity);
if (dxfEntity != null)
{
dxfDoc.Entities.Add(dxfEntity);
}
}
// 保存文件
dxfDoc.Save(filePath);
}
}
14.4 SketchUp格式支持
14.4.1 SketchUp导入
public class SketchUpImporter
{
/// <summary>
/// 导入SketchUp文件
/// </summary>
public LcDocument Import(string filePath)
{
var document = new LcDocument();
// 解析SKP文件
using (var reader = new SkpReader(filePath))
{
// 导入材质
foreach (var material in reader.Materials)
{
ImportMaterial(material, document);
}
// 导入组件定义
foreach (var component in reader.ComponentDefinitions)
{
ImportComponent(component, document);
}
// 导入几何体
foreach (var face in reader.Faces)
{
ImportFace(face, document);
}
foreach (var edge in reader.Edges)
{
ImportEdge(edge, document);
}
}
return document;
}
/// <summary>
/// 导入SketchUp面(转换为网格体)
/// </summary>
private void ImportFace(SkpFace face, LcDocument document)
{
var mesh = new LcMesh3d();
// 转换顶点
foreach (var vertex in face.Vertices)
{
mesh.Vertices.Add(new Point3d(
vertex.X, vertex.Y, vertex.Z));
}
// 转换三角面
var triangulated = face.Triangulate();
foreach (var tri in triangulated)
{
mesh.FaceIndices.Add(tri.Index0);
mesh.FaceIndices.Add(tri.Index1);
mesh.FaceIndices.Add(tri.Index2);
}
mesh.RecalculateNormals();
if (face.Material != null)
{
mesh.Material = new MaterialInfo
{
Name = face.Material.Name,
DiffuseColor = ConvertSkpColor(face.Material.Color)
};
}
document.Entities.Add(mesh);
}
}
14.5 原生格式
14.5.1 LightCAD文件格式设计
LightCAD的原生文件格式采用二进制格式,能够完整保存所有CAD数据:
public class NativeFormatSerializer
{
private const string MAGIC = "LCAD";
private const int VERSION = 1;
/// <summary>
/// 保存文档
/// </summary>
public void Save(LcDocument document, string filePath)
{
using var stream = File.Create(filePath);
using var writer = new BinaryWriter(stream);
// 文件头
writer.Write(MAGIC.ToCharArray());
writer.Write(VERSION);
writer.Write(DateTime.UtcNow.ToBinary());
// 文档元数据
writer.Write(document.Name ?? "");
writer.Write(document.Guid.ToString());
// 单位设置
WriteUnitSettings(writer, document.Units);
// 图层表
var layers = document.Layers.GetAll();
writer.Write(layers.Count);
foreach (var layer in layers)
{
WriteLayer(writer, layer);
}
// 块定义
var blocks = document.Blocks.GetAll();
writer.Write(blocks.Count);
foreach (var block in blocks)
{
WriteBlock(writer, block);
}
// 实体
var entities = document.Entities.ToList();
writer.Write(entities.Count);
foreach (var entity in entities)
{
WriteEntity(writer, entity);
}
}
/// <summary>
/// 加载文档
/// </summary>
public LcDocument Load(string filePath)
{
using var stream = File.OpenRead(filePath);
using var reader = new BinaryReader(stream);
// 验证文件头
var magic = new string(reader.ReadChars(4));
if (magic != MAGIC)
throw new InvalidDataException("无效的LightCAD文件");
var version = reader.ReadInt32();
var timestamp = DateTime.FromBinary(reader.ReadInt64());
var document = new LcDocument
{
Name = reader.ReadString(),
Guid = new LcGuid(reader.ReadString())
};
// 读取单位设置
document.Units = ReadUnitSettings(reader);
// 读取图层
var layerCount = reader.ReadInt32();
for (int i = 0; i < layerCount; i++)
{
ReadLayer(reader, document);
}
// 读取块定义
var blockCount = reader.ReadInt32();
for (int i = 0; i < blockCount; i++)
{
ReadBlock(reader, document);
}
// 读取实体
var entityCount = reader.ReadInt32();
for (int i = 0; i < entityCount; i++)
{
var entity = ReadEntity(reader);
if (entity != null)
{
document.Entities.Add(entity);
}
}
return document;
}
/// <summary>
/// 写入实体(带类型标识)
/// </summary>
private void WriteEntity(BinaryWriter writer, LcEntity entity)
{
// 写入类型标识
writer.Write(entity.TypeName);
// 写入通用属性
writer.Write(entity.Handle);
writer.Write(entity.Guid.ToString());
writer.Write(entity.LayerName);
WriteColor(writer, entity.Color);
writer.Write(entity.LineType ?? "");
writer.Write(entity.LineWeight);
writer.Write(entity.IsVisible);
// 写入特定属性
switch (entity)
{
case LcLine line:
WritePoint2d(writer, line.StartPoint);
WritePoint2d(writer, line.EndPoint);
break;
case LcCircle circle:
WritePoint2d(writer, circle.Center);
writer.Write(circle.Radius);
break;
case LcArc arc:
WritePoint2d(writer, arc.Center);
writer.Write(arc.Radius);
writer.Write(arc.StartAngle);
writer.Write(arc.EndAngle);
writer.Write(arc.IsCounterClockwise);
break;
// ... 其他实体类型
}
}
}
14.6 格式转换工具
14.6.1 统一转换接口
public class FormatConverter
{
/// <summary>
/// 通用文件导入
/// </summary>
public LcDocument Import(string filePath)
{
var extension = Path.GetExtension(filePath).ToLower();
return extension switch
{
".dwg" => new DwgImporter().Import(filePath),
".dxf" => new DxfImporter().Import(filePath),
".skp" => new SketchUpImporter().Import(filePath),
".lcad" => new NativeFormatSerializer().Load(filePath),
_ => throw new NotSupportedException(
$"不支持的文件格式:{extension}")
};
}
/// <summary>
/// 通用文件导出
/// </summary>
public void Export(LcDocument document, string filePath)
{
var extension = Path.GetExtension(filePath).ToLower();
switch (extension)
{
case ".dwg":
new DwgExporter().Export(document, filePath);
break;
case ".dxf":
new DxfExporter().Export(document, filePath);
break;
case ".lcad":
new NativeFormatSerializer().Save(document, filePath);
break;
default:
throw new NotSupportedException(
$"不支持的导出格式:{extension}");
}
}
/// <summary>
/// 批量格式转换
/// </summary>
public void BatchConvert(string inputDir, string outputDir,
string inputFormat, string outputFormat)
{
var files = Directory.GetFiles(inputDir, $"*.{inputFormat}");
foreach (var file in files)
{
var document = Import(file);
var outputPath = Path.Combine(outputDir,
Path.ChangeExtension(
Path.GetFileName(file), outputFormat));
Export(document, outputPath);
}
}
}
14.7 本章小结
本章详细介绍了LightCAD的文件格式支持和数据交换能力。LightCAD通过ODA SDK实现了DWG格式的完整读写,通过netDxf库支持DXF格式,还支持SketchUp格式的导入导出。原生的LightCAD文件格式采用高效的二进制编码,能够完整保存所有CAD数据。统一的格式转换接口为用户提供了便捷的文件操作体验。
上一章:第十三章:用户界面框架
下一章:第十五章:插件系统与扩展开发