可直接编译运行 c#解析dxf可读取圆直线弧多段线源码-无封装缩放拖拽 可读取坐标信息 支持多...

可直接编译运行 c#解析dxf可读取圆直线弧多段线源码-无封装缩放拖拽 可读取坐标信息 支持多种版本的CAD 可导出G代码

最近在折腾CAD文件解析,发现DXF这东西虽然结构复杂但还挺有意思的。用C#撸了个解析器,能读取圆、直线、弧、多段线这些基础图形,顺手还做了G代码导出功能。咱们直接从代码层面聊聊实现思路。

先看这段读取直线的基础代码:

csharp 复制代码
var lines = File.ReadAllLines("sample.dxf");
for (int i = 0; i < lines.Length; i++)
{
    if (lines[i] == "LINE")
    {
        var line = new DxfLine();
        while (lines[++i] != "0")
        {
            var code = lines[i];
            var value = lines[++i];
            
            switch(code)
            {
                case "10": line.StartX = double.Parse(value); break;
                case "20": line.StartY = double.Parse(value); break;
                case "11": line.EndX = double.Parse(value); break;
                case "21": line.EndY = double.Parse(value); break;
            }
        }
        Console.WriteLine($"直线坐标:({line.StartX},{line.StartY}) -> ({line.EndX},{line.EndY})");
    }
}

这代码看着糙但实用,遍历DXF文本按组码抓数据。注意LINE实体的组码10/20是起点,11/21是终点。DXF的坐标对总是成对出现,处理时要记得X在前Y在后。

遇到多段线就刺激了。旧版用POLYLINE,新版用LWPOLYLINE,这俩结构差异不小。看这段处理逻辑:

csharp 复制代码
if (entityType == "LWPOLYLINE")
{
    var poly = new Polyline();
    while ((code = lines[++i]) != "0")
    {
        value = lines[++i];
        if (code == "90") // 顶点数
        {
            int vertexCount = int.Parse(value);
            poly.Vertices = new List<Point>(vertexCount);
        }
        else if (code == "10") // X坐标
        {
            x = double.Parse(value);
            flag = true;
        }
        else if (code == "20" && flag) // Y坐标
        {
            poly.Vertices.Add(new Point(x, double.Parse(value)));
            flag = false;
        }
    }
}

这里用了个flag标记来捕获坐标对,因为DXF的顶点坐标是交替出现的。处理旧版POLYLINE更麻烦,得在顶点段(VERTEX)里逐个抓点,最后还要等SEQEND结束符,代码能多写二十行。

可直接编译运行 c#解析dxf可读取圆直线弧多段线源码-无封装缩放拖拽 可读取坐标信息 支持多种版本的CAD 可导出G代码

说到版本兼容,关键在HEADER段找$ACADVER字段。不同版本组码有变化,比如圆弧的起始/终止角度在R12用50/51,新版可能用其他组码。咱们用个字典来映射:

csharp 复制代码
var versionMappings = new Dictionary<string, Func<string, string>>()
{
    {"AC1018", code => code == "1001" ? "start_angle" : null}, // 2004版
    {"AC1021", code => code == "72" ? "start_angle" : null}    // 2007版
};

导出G代码这块更有意思。把几何数据转成机床指令,注意坐标系的Y轴要反转(CAD是Y向上,机床通常是Y向下)。看这个转换片段:

csharp 复制代码
stringBuilder.AppendLine($"G01 X{point.X:F3} Y{-point.Y:F3} F500");

圆弧处理要算圆心和方向。用DXF的起始角/终止角转成G02/G03指令:

csharp 复制代码
var arcCmd = IsClockwise ? "G02" : "G03";
var center = new Point(
    (start.X + end.X)/2 + radius * Math.Cos(midAngle),
    (start.Y + end.Y)/2 + radius * Math.Sin(midAngle)
);

最后说下缩放拖拽的实现。别被唬住,本质就是矩阵变换。比如平移操作:

csharp 复制代码
public void Pan(double offsetX, double offsetY)
{
    foreach (var entity in entities)
    {
        if (entity is Line line)
        {
            line.StartX += offsetX;
            line.StartY += offsetY;
            line.EndX += offsetX;
            line.EndY += offsetY;
        }
        // 其他实体类型同理...
    }
}

这代码直接粗暴但有效,真要优化可以用访客模式,不过咱说好了不封装嘛。

项目扔GitHub上后,有老哥反馈说处理复杂图纸会内存溢出。一查发现是暴力读整个文件导致的,后来改成流式读取,内存占用直接从500M降到50M。所以说,处理DXF还是得边读边解析,别头铁全加载到内存。

总之这项目验证了:用C#搞DXF解析完全可行,关键是多准备点测试图纸。下次考虑加点三维实体支持,不过那是另一个坑了...

相关推荐
张32310 小时前
Ansible实施任务控制
linux·ansible
张32312 小时前
Ansible Playbook
ansible
张32313 小时前
Ansible文件部署
服务器·ansible
张32313 小时前
Ansible介绍
ansible
热爱Liunx的丘丘人1 天前
Ansible的Playbook案例一
linux·运维·服务器·ansible
小梦爱安全1 天前
Ansible剧本1
java·网络·ansible
WJ.Polar1 天前
Ansible任务控制
linux·运维·网络·python·ansible
热爱Liunx的丘丘人1 天前
PlayBook常用的模块编写
linux·服务器·ansible
淼淼爱喝水2 天前
Ansible Playbook 入门实战:自动化创建 Linux 用户
linux·运维·服务器·网络·ansible
热爱Liunx的丘丘人2 天前
Ansible-doc及常用模块
linux·运维·服务器·ansible