You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何用netDxf检测DXF文件中文字与其他图元的重叠问题

用netDxf检测DXF文件中文字与图元的重叠问题

我尝试使用netDxf库检测DXF文件中文字与圆、多段线、点等图元的重叠情况,但当前代码无法正常运行。已获取圆的半径、圆心坐标(X,Y)以及文字位置坐标(X,Y),附上当前C#代码,希望了解如何通过netDxf正确实现该检测功能。示例DWG截图如下:

DXF文件中文字与圆重叠的截图

原代码

string directoryPath = @"C:\Users\Desktop";
string fileName = "Drawing2.dxf";
string filePath = Path.Combine(directoryPath, fileName);

try
{
    if (File.Exists(filePath))
    {
        // File exists, proceed with loading and checking for overlap
        DxfDocument loaded = DxfDocument.Load(filePath);
        
        List<EntityObject> entityList = loaded.Entities.All.ToList();
        Vector2 TcurrentPosition = Vector2.Zero;
        Vector2 ComputeB= Vector2.Zero;
        foreach (EntityObject entity in entityList)
        {
            if (entity is Text textEntity)
            {
                // Retrieve the current text position
                TcurrentPosition = new Vector2(textEntity.Position.X, textEntity.Position.Y);

                // Display or process the retrieved values as needed
                Console.WriteLine($"Text Position: X: {textEntity.Position.X}, Y:{textEntity.Position.Y}");
            }
            // Add more conditions for other entity types if needed
            if (entity is Circle circleEntity)
            {
                // Retrieve the current circle center position
                Vector2 centerPosition = new Vector2(circleEntity.Center.X, circleEntity.Center.Y);

                // Display or process the retrieved values as needed
                double radius = circleEntity.Radius;
                Console.WriteLine($"Circle Position: X: {centerPosition.X}, Y: {centerPosition.Y}, Radius: {radius}");

                // Example: Check if a specific point overlaps with the circle
                Vector2 point1ToCheck = TcurrentPosition;
                Vector2 point2ToCheck = centerPosition;         
                
                double distance = Math.Sqrt(Math.Pow(point1ToCheck.X - point2ToCheck.X, 2) + Math.Pow(point1ToCheck.Y - point2ToCheck.Y, 2));
                if(distance>radius)
                
                {
                    Console.WriteLine("Overlap detected!");
                }
                else
                {
                    Console.WriteLine("There is no Overlap detected!");
                }
            }
        }
    }
    else
    {
        Console.WriteLine($"Error: File not found at {filePath}");
    }
}
catch (Exception ex)
{
    Console.WriteLine($"Error: {ex.Message}");
}

问题分析

原代码存在两个核心问题:

  1. 逻辑错误:遍历实体时仅记录最后一个文字的位置,每个圆都和该位置对比,无法实现所有文字与所有圆的逐一检测。
  2. 判断条件错误:将文字视为单点,且重叠判断逻辑写反(distance>radius时判定重叠,实际应为文字区域与圆有交集)。文字有实际尺寸,需计算其包围盒再判断重叠。

正确实现方案

步骤说明

  1. 分离提取所有文字实体和待检测的图元(圆、多段线、点)。
  2. 计算每个文字的旋转包围盒:考虑文字的高度、宽度、旋转角度,生成包含文字的最小矩形。
  3. 针对不同图元类型,分别实现重叠检测逻辑:
    • 圆与文字:判断圆是否与文字包围盒相交。
    • 多段线与文字:判断多段线是否与文字包围盒相交。
    • 点与文字:判断点是否在文字包围盒内部。

修正后的代码

using netDxf;
using netDxf.Entities;
using netDxf.Math;
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;

namespace DxfOverlapDetection
{
    class Program
    {
        static void Main(string[] args)
        {
            string directoryPath = @"C:\Users\Desktop";
            string fileName = "Drawing2.dxf";
            string filePath = Path.Combine(directoryPath, fileName);

            try
            {
                if (!File.Exists(filePath))
                {
                    Console.WriteLine($"Error: File not found at {filePath}");
                    return;
                }

                DxfDocument loaded = DxfDocument.Load(filePath);
                
                // 提取所有文字实体
                List<Text> textEntities = loaded.Entities.OfType<Text>().ToList();
                // 提取所有待检测的图元
                List<Circle> circleEntities = loaded.Entities.OfType<Circle>().ToList();
                List<Polyline> polylineEntities = loaded.Entities.OfType<Polyline>().ToList();
                List<Point> pointEntities = loaded.Entities.OfType<Point>().ToList();

                // 遍历每个文字,检测与所有图元的重叠
                foreach (Text text in textEntities)
                {
                    Console.WriteLine($"=== 检测文字: {text.Value} (插入点: X={text.Position.X:F2}, Y={text.Position.Y:F2}) ===");
                    // 计算文字的旋转包围盒
                    BoundingBox textBbox = CalculateTextBoundingBox(text);

                    // 检测与圆的重叠
                    foreach (Circle circle in circleEntities)
                    {
                        bool isOverlap = IsCircleOverlapWithBbox(circle, textBbox);
                        Console.WriteLine($"与圆(圆心: X={circle.Center.X:F2}, Y={circle.Center.Y:F2}, 半径={circle.Radius:F2})重叠: {isOverlap}");
                    }

                    // 检测与多段线的重叠
                    foreach (Polyline polyline in polylineEntities)
                    {
                        bool isOverlap = IsPolylineOverlapWithBbox(polyline, textBbox);
                        Console.WriteLine($"与多段线重叠: {isOverlap}");
                    }

                    // 检测与点的重叠
                    foreach (Point point in pointEntities)
                    {
                        bool isOverlap = IsPointInBbox(point.Position, textBbox);
                        Console.WriteLine($"与点(X={point.Position.X:F2}, Y={point.Position.Y:F2})重叠: {isOverlap}");
                    }
                }
            }
            catch (Exception ex)
            {
                Console.WriteLine($"Error: {ex.Message}");
            }
        }

        // 计算文字的旋转包围盒
        private static BoundingBox CalculateTextBoundingBox(Text text)
        {
            // 文字的高度(从基线到顶部的距离)
            double height = text.Height;
            // 文字的总宽度(包含所有字符的宽度)
            double width = text.TextWidth();
            // 插入点
            Vector3 insertPoint = text.Position;
            // 旋转角度(弧度)
            double rotation = text.Rotation * Math.PI / 180;

            // 计算文字四个顶点的坐标(相对于插入点)
            Vector3[] localVertices = new Vector3[]
            {
                new Vector3(0, 0, 0), // 插入点(基线左下角)
                new Vector3(width, 0, 0), // 基线右下角
                new Vector3(width, height, 0), // 右上角
                new Vector3(0, height, 0) // 左上角
            };

            // 应用旋转和平移,得到世界坐标下的顶点
            List<Vector3> worldVertices = new List<Vector3>();
            foreach (Vector3 v in localVertices)
            {
                // 旋转
                double x = v.X * Math.Cos(rotation) - v.Y * Math.Sin(rotation);
                double y = v.X * Math.Sin(rotation) + v.Y * Math.Cos(rotation);
                // 平移到插入点
                worldVertices.Add(new Vector3(insertPoint.X + x, insertPoint.Y + y, insertPoint.Z));
            }

            // 创建包围盒
            return new BoundingBox(worldVertices);
        }

        // 判断圆是否与包围盒重叠
        private static bool IsCircleOverlapWithBbox(Circle circle, BoundingBox bbox)
        {
            // 计算圆心到包围盒的最近点
            Vector3 closestPoint = bbox.ClosestPointTo(circle.Center);
            // 计算圆心到最近点的距离
            double distance = Vector3.Distance(circle.Center, closestPoint);
            // 如果距离小于等于半径,则重叠
            return distance <= circle.Radius;
        }

        // 判断多段线是否与包围盒重叠
        private static bool IsPolylineOverlapWithBbox(Polyline polyline, BoundingBox bbox)
        {
            // 遍历多段线的所有线段,判断是否与包围盒相交
            List<Vector3> vertices = polyline.Vertexes.Select(v => v.Position).ToList();
            for (int i = 0; i < vertices.Count - 1; i++)
            {
                LineSegment segment = new LineSegment(vertices[i], vertices[i + 1]);
                if (bbox.Intersects(segment))
                {
                    return true;
                }
            }
            // 也可以判断多段线的包围盒是否与文字包围盒相交(更快但精度稍低)
            // return polyline.BoundingBox.Intersects(bbox);
            return false;
        }

        // 判断点是否在包围盒内
        private static bool IsPointInBbox(Vector3 point, BoundingBox bbox)
        {
            return bbox.Contains(point);
        }
    }
}

代码说明

  • CalculateTextBoundingBox:根据文字的高度、宽度、旋转角度生成精确的包围盒,解决了原代码将文字视为单点的问题。
  • IsCircleOverlapWithBbox:通过计算圆心到包围盒的最近点距离,判断圆与文字区域是否重叠。
  • IsPolylineOverlapWithBbox:遍历多段线的每个线段,判断是否与文字包围盒相交。
  • 所有文字与图元逐一配对检测,解决了原代码仅检测最后一个文字的逻辑问题。

内容的提问来源于stack exchange,提问作者Ajithkumar T

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.28 05:44:56