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

相关推荐
Maggie_ssss_supp1 天前
Linux-ansible自动化运维
运维·自动化·ansible
迎仔1 天前
10-算力中心运维三剑客:Ansible + Jenkins + K8s 高效实战
运维·kubernetes·ansible·jenkins
识途老码3 天前
25.ansible的hostname模块
ansible·hostname
Cloud Traveler6 天前
Ansible+cpolar:NAS 远程自动化运维方案
ansible
陈桴浮海6 天前
【Linux&Ansible】学习笔记合集七
linux·学习·ansible
only_Klein8 天前
Ansible自动化部署Kubernetes
kubernetes·自动化·ansible
陈桴浮海8 天前
【Linux&Ansible】学习笔记合集五
linux·云原生·ansible
杨了个杨89829 天前
Ansible Playbook 的常用模板
java·服务器·ansible
陈桴浮海9 天前
【Linux&Ansible】学习笔记合集四
linux·学习·ansible