可直接编译运行 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解析完全可行,关键是多准备点测试图纸。下次考虑加点三维实体支持,不过那是另一个坑了...

相关推荐
有毒的教程4 天前
Ansible批量操作自动化完整教程:批量部署服务、配置同步、软件更新实战
运维·自动化·ansible
Hy行者勇哥9 天前
用Cursor智能编写Ansible/Terraform脚本,打通CI/CD链路
ci/cd·ansible·terraform
芷栀夏11 天前
飞牛NAS怎么部署Immich?家庭照片自动备份与远程访问教程
服务器·nginx·ansible
悠然南风21 天前
Ansible常见模块总结及LDAP Role 编写与调试
ansible
祺风挽楠1 个月前
ansible编辑
网络·ansible
芳心粽伙饭1 个月前
Ansible课后作业
ansible
烁3471 个月前
Ansible初识
ansible
烁3471 个月前
Ansible安装部署调试
ansible
烁3471 个月前
Ansible命令
ansible
小义_1 个月前
【Ansible】(三)基础配置与连接设置
云原生·ansible