【WPF】c#读取CAD的dxf文件,并基于Canvas将读取到的数据重新描绘到界面

发布于:2025-03-18 ⋅ 阅读:(17) ⋅ 点赞:(0)

1.下载安装netDxf库
在这里插入图片描述
2.读取dxf文件,数据存储到DataTable

using netDxf;
using netDxf.Entities;
/// <summary>
    /// 读取CAD的Dxf文件数据
    /// </summary>
    public class DxfHelperHtility
    {
        /// <summary>
        /// 读取CAD文件数据
        /// </summary>
        /// <param name="fileName"></param>
        /// <returns></returns>
        public static DataTable ReadDxf(string fileName)
        {
            DataTable dt = CreatDataTable();
            try
            {
                // 加载DXF文件
                DxfDocument dxf = DxfDocument.Load(fileName);
                netDxf.Tables.UCS ucs =dxf.DrawingVariables.CurrentUCS;
                netDxf.Collections.ImageDefinitions dd =dxf.ImageDefinitions;
                bool bRow = false;
                // 遍历所有实体
                foreach (EntityObject entity in dxf.Entities.All)
                {
                    bRow = false;
                    //添加数据行
                    DataRow drRow = dt.NewRow();
                    switch (entity)
                    {
                        case Line line:
                            //直线
                            drRow["DrawingType"] = 0;
                            drRow["StartPointX"] = ToConver(line.StartPoint.X, ucs.Origin.X);
                            drRow["StartPointY"] = ToConver(line.StartPoint.Y, ucs.Origin.Y);
                            drRow["EndPointX"] = ToConver(line.EndPoint.X, ucs.Origin.X);
                            drRow["EndPointY"] = ToConver(line.EndPoint.Y, ucs.Origin.Y);
                            drRow["Thickness"] = line.Thickness;
                            bRow = true;
                            break;
                        case Circle circle:
                            //圆形
                            drRow["DrawingType"] = 1;
                            drRow["StartPointX"] = ToConver(circle.Center.X, ucs.Origin.X);
                            drRow["StartPointY"] = ToConver(circle.Center.Y, ucs.Origin.Y);
                            drRow["Radius"] = circle.Radius;
                            drRow["Thickness"] = circle.Thickness;
                            bRow = true;
                            break;
                        case Arc arc:
                            //弧形
                            drRow["DrawingType"] = 2;
                            drRow["StartPointX"] = ToConver(arc.Center.X, ucs.Origin.X);
                            drRow["StartPointY"] = ToConver(arc.Center.Y, ucs.Origin.Y);
                            drRow["Radius"] = arc.Radius;
                            drRow["StartAngle"] = arc.StartAngle;
                            drRow["EndAngle"] = arc.EndAngle;
                            drRow["Thickness"] = arc.Thickness;
                            bRow = true;
                            break;
                        case Text text:
                            //文本
                            break;
                        case Ellipse ellipse:
                            //椭圆
                            drRow["DrawingType"] = 4;
                            drRow["StartPointX"] = ToConver(ellipse.Center.X, ucs.Origin.X);
                            drRow["StartPointY"] = ToConver(ellipse.Center.Y, ucs.Origin.Y);
                            drRow["MajorAxis"] = ellipse.MajorAxis;
                            drRow["MinorAxis"] = ellipse.MinorAxis;
                            drRow["StartAngle"] = ellipse.StartAngle;
                            drRow["EndAngle"] = ellipse.EndAngle;
                            drRow["Thickness"] = ellipse.Thickness;
                            bRow = true;
                            break;
                        case Polyline2D polyline2D:
                            drRow["DrawingType"] = 5;
                            drRow["Thickness"] = polyline2D.Thickness;
                            string data = "";
                            Polyline2DVertex startVertex = polyline2D.Vertexes[0];
                            Polyline2DVertex nextVertex;
                            double radius = 0;
                            for (int i = 0; i < polyline2D.Vertexes.Count; i++)
                            {
                                radius = 0;
                                Polyline2DVertex curVertex = polyline2D.Vertexes[i];
                                if (curVertex.Bulge != 0)
                                {
                                    //有凸度,计算半径
                                    if (i == polyline2D.Vertexes.Count)
                                    {
                                        nextVertex = startVertex;
                                    }
                                    else
                                    {
                                        nextVertex = polyline2D.Vertexes[i + 1];
                                    }
                                    radius = CalBulgeRadius(curVertex.Position.X, curVertex.Position.Y, nextVertex.Position.X, nextVertex.Position.Y, curVertex.Bulge);
                                }
                                data += string.Format("X:{0},Y:{1},Bulge:{2},StartWidth:{3},EndWidth:{4},Radius:{5}|", ToConver(curVertex.Position.X, ucs.Origin.X), ToConver(curVertex.Position.Y, ucs.Origin.Y), curVertex.Bulge, curVertex.StartWidth, curVertex.EndWidth, radius);
                            }
                            drRow["Data"] = data;
                            bRow = true;
                            break;
                        default:
                            break;
                    }

                    if (bRow)
                    {
                        dt.Rows.Add(drRow);
                    }
                }
            }
            catch (Exception ex)
            {
                
            }
            return dt;
        }

        /// <summary>
        /// 坐标转换
        /// </summary>
        /// <param name="value">坐标值</param>
        /// <param name="ucs">用户原点坐标</param>
        /// <returns></returns>
        private static int ToConver(double value,double ucs)
        {
            int result = 0;
            result = (int)Math.Round(value- ucs);
            return result;
        }

        /// <summary>
        /// 动态创建表格列
        /// </summary>
        /// <returns></returns>
        private static DataTable CreatDataTable()
        {
            DataTable dt = new DataTable();
            try
            {
                //添加列
                dt.Columns.Add("DrawingType", typeof(int));//类型
                dt.Columns.Add("StartPointX", typeof(double));//起点X坐标
                dt.Columns.Add("StartPointY", typeof(double));//起点Y坐标
                dt.Columns.Add("EndPointX", typeof(double));//终点X坐标
                dt.Columns.Add("EndPointY", typeof(double));//起点Y坐标
                dt.Columns.Add("Radius", typeof(double));//圆半径
                dt.Columns.Add("StartAngle", typeof(double));//起点角度
                dt.Columns.Add("EndAngle", typeof(double));//终点角度
                dt.Columns.Add("MajorAxis", typeof(double));//椭圆长轴
                dt.Columns.Add("MinorAxis", typeof(double));//椭圆短轴
                dt.Columns.Add("Thickness", typeof(double));//线宽
                dt.Columns.Add("Data", typeof(string));//线宽
            }
            catch (Exception ex)
            {

            }
            return dt;
        }
        /// <summary>
        /// 根据两点和凸度,计算半径
        /// </summary>
        /// <param name="x1"></param>
        /// <param name="y1"></param>
        /// <param name="x2"></param>
        /// <param name="y2"></param>
        /// <param name="bulge"></param>
        /// <returns></returns>
        public static double CalBulgeRadius(double x1, double y1, double x2, double y2, double bulge)
        {
            double radius = 0;
            try
            {
                if (bulge == 0)
                    return radius;
                //计算顶点角度
                double cicleAngle = Math.Atan(bulge) * 4;
                //两点之间的距离
                double pointLen = Math.Sqrt((x1 - x2) * (x1 - x2) + (y1 - y2) * (y1 - y2));
                //根据正玄值反推
                radius = (pointLen / 2) / Math.Sin(cicleAngle / 2);
                return Math.Abs(radius);
            }
            catch (Exception ex)
            {

            }
            return radius;
        }
    }

特别注意:如果用户画的图不是默认原点,而是自定义原点,需要获取用户坐标原点,其他线段点需要减去用户坐标原点才能得到正确的坐标

  //获取用户坐标系(UCS)的原点坐标
  netDxf.Tables.UCS ucs =dxf.DrawingVariables.CurrentUCS;

至此完成了dxf文件读取并将数据存储到DataTable,供后续处理。
3.DataTable数据转换成通用数据,供上层使用

/// <summary>
        /// 读取CAD文件数据
        /// </summary>
        /// <param name="path"></param>
        /// <returns></returns>
        public static List<DxfModel> ReadDxf(string path)
        {
            List<DxfModel> list = new List<DxfModel>();
            DataTable dt = DxfHelperHtility.ReadDxf(path);
            if (dt == null || dt.Rows.Count <= 0)
            {
                return list;
            }
            for (int i = 0; i < dt.Rows.Count; i++)
            {
                DxfModel dxfModel = new DxfModel();
                int drawingType = Convert.ToInt16(dt.Rows[i]["DrawingType"].ToString().Trim());
                switch (drawingType)
                {
                    case 0:
                        //直线
                        dxfModel.DrawingType = drawingType;
                        dxfModel.StartPointX= Convert.ToInt16(dt.Rows[i]["StartPointX"].ToString().Trim());
                        dxfModel.StartPointY = Convert.ToInt16(dt.Rows[i]["StartPointY"].ToString().Trim());
                        dxfModel.EndPointX = Convert.ToInt16(dt.Rows[i]["EndPointX"].ToString().Trim());
                        dxfModel.EndPointY = Convert.ToInt16(dt.Rows[i]["EndPointY"].ToString().Trim());
                        dxfModel.Thickness = Convert.ToDouble(dt.Rows[i]["Thickness"].ToString().Trim());
                        list.Add(dxfModel);
                        break;
                    case 1:
                        //圆形
                        dxfModel.DrawingType = drawingType;
                        dxfModel.StartPointX = Convert.ToInt16(dt.Rows[i]["StartPointX"].ToString().Trim());
                        dxfModel.StartPointY = Convert.ToInt16(dt.Rows[i]["StartPointY"].ToString().Trim());
                        dxfModel.Radius = Convert.ToDouble(dt.Rows[i]["Radius"].ToString().Trim());
                        dxfModel.Thickness = Convert.ToDouble(dt.Rows[i]["Thickness"].ToString().Trim());
                        list.Add(dxfModel);
                        break;
                    case 2:
                        //圆弧
                        dxfModel.DrawingType = drawingType;
                        dxfModel.StartPointX = Convert.ToInt16(dt.Rows[i]["StartPointX"].ToString().Trim());
                        dxfModel.StartPointY = Convert.ToInt16(dt.Rows[i]["StartPointY"].ToString().Trim());
                        dxfModel.Radius = Convert.ToDouble(dt.Rows[i]["Radius"].ToString().Trim());
                        dxfModel.StartAngle = Convert.ToDouble(dt.Rows[i]["StartAngle"].ToString().Trim());
                        dxfModel.EndAngle = Convert.ToDouble(dt.Rows[i]["EndAngle"].ToString().Trim());
                        dxfModel.Thickness = Convert.ToDouble(dt.Rows[i]["Thickness"].ToString().Trim());
                        list.Add(dxfModel);
                        break;
                    case 3:
                        //文本
                        break;
                    case 4:
                        //椭圆
                        dxfModel.DrawingType = drawingType;
                        dxfModel.StartPointX = Convert.ToInt16(dt.Rows[i]["StartPointX"].ToString().Trim());
                        dxfModel.StartPointY = Convert.ToInt16(dt.Rows[i]["StartPointY"].ToString().Trim());
                        dxfModel.MajorAxis = Convert.ToDouble(dt.Rows[i]["MajorAxis"].ToString().Trim());
                        dxfModel.MinorAxis = Convert.ToDouble(dt.Rows[i]["MinorAxis"].ToString().Trim());
                        dxfModel.StartAngle = Convert.ToDouble(dt.Rows[i]["StartAngle"].ToString().Trim());
                        dxfModel.EndAngle = Convert.ToDouble(dt.Rows[i]["EndAngle"].ToString().Trim());
                        dxfModel.Thickness = Convert.ToDouble(dt.Rows[i]["Thickness"].ToString().Trim());
                        list.Add(dxfModel);
                        break;
                    case 5:
                        //Polyline2D
                        dxfModel.DrawingType = drawingType;
                        dxfModel.Thickness = Convert.ToDouble(dt.Rows[i]["Thickness"].ToString().Trim());
                        //解析图形坐标
                        string[] datas = dt.Rows[i]["Data"].ToString().Trim().Split('|');
                        for (int k = 0; k < datas.Count() - 1; k++)
                        {
                            Polyline polyline = new Polyline();
                            string[] messageData = datas[k].Split(',');
                            polyline.X = Convert.ToDouble(messageData[0].Split(':')[1]);
                            polyline.Y = Convert.ToDouble(messageData[1].Split(':')[1]);
                            polyline.Bulge = Convert.ToDouble(messageData[2].Split(':')[1]);
                            polyline.StartWidth = Convert.ToDouble(messageData[3].Split(':')[1]);
                            polyline.EndWidth = Convert.ToDouble(messageData[4].Split(':')[1]);
                            polyline.Radius = Convert.ToDouble(messageData[5].Split(':')[1]);
                            dxfModel.Polylines.Add(polyline);
                        }
                        list.Add(dxfModel);
                        break;
                    default:
                        break;
                }
            }
            return list;
        }

4.基于Canvas画图

/// <summary>
   /// 画图
     /// </summary>
     private void Draw()
     {
         try
         {
             if (string.IsNullOrWhiteSpace(DxfName))
             {
                 return;
             }
             Path path = new Path();
             PathGeometry pathGeometry = new PathGeometry();
             PathFigure pathFigure = new PathFigure();
             Point startPoint = new Point();
             Point endPoint = new Point();
             Point prePoint = startPoint;
             List<DxfModel> list =FileManageBll.ReadDxf(DxfName);
             foreach (var item in list)
             {
                 switch (item.DrawingType)
                 {
                     case 0://直线
                         // 创建Path对象
                         path = new Path();
                         path.Stroke = System.Windows.Media.Brushes.White;
                         path.StrokeThickness = 1;
                         // 创建PathGeometry对象
                         pathGeometry = new PathGeometry();
                         // 创建PathFigure对象
                         pathFigure = new PathFigure();
                         pathFigure.StartPoint = new System.Windows.Point(item.StartPointX, -item.StartPointY);
                         // 创建LineSegment对象并添加到PathFigure
                         pathFigure.Segments.Add(new LineSegment(new System.Windows.Point(item.EndPointX, -item.EndPointY), true));
                         // 将PathFigure添加到PathGeometry
                         pathGeometry.Figures.Add(pathFigure);
                         // 设置Path的Data属性为PathGeometry对象
                         path.Data = pathGeometry;
                         // 将path添加到myCanvas1中
                         this.mainWindow.myCanvas.Children.Add(path);
                         break;
                     case 1://System.Windows.Shapes.Ellipse ellipse = new System.Windows.Shapes.Ellipse
                         {
                             Width = item.Radius,
                             Height = item.Radius,
                             StrokeThickness = 1,
                             Stroke = System.Windows.Media.Brushes.White
                         };
                         Canvas.SetLeft(ellipse, item.StartPointX);
                         Canvas.SetTop(ellipse, -item.StartPointY);
                         this.mainWindow.myCanvas.Children.Add(ellipse);
                         break;
                     case 2: //圆弧
                         // 将角度转换为弧度
                         double startRadians = item.StartAngle * Math.PI / 180;
                         double endRadians = item.EndAngle * Math.PI / 180;

                         // 计算起点和终点的坐标(注意Y轴方向)
                         startPoint = new Point(
                             item.StartPointX + item.Radius * Math.Cos(startRadians),
                             -item.StartPointY - item.Radius * Math.Sin(startRadians));
                         endPoint = new Point(
                            item.StartPointX + item.Radius * Math.Cos(endRadians),
                            -item.StartPointY - item.Radius * Math.Sin(endRadians));

                         bool IsLargeArc = false;
                         if ((item.EndAngle - item.StartAngle + 360) % 360 >= 180)
                         {
                             //大弧
                             IsLargeArc = true;
                         }
                         SweepDirection direction = SweepDirection.Counterclockwise;
                         //if (item.StartAngle > item.EndAngle)
                         //{
                         //    //逆时针
                         //    direction = SweepDirection.Clockwise;
                         //}
                         path = new Path();
                         pathGeometry = new PathGeometry();
                         ArcSegment arc = new ArcSegment(endPoint, new Size(item.Radius, item.Radius), 0, IsLargeArc, direction, true);

                         PathFigure figure = new PathFigure();
                         figure.StartPoint = startPoint;
                         figure.Segments.Add(arc);
                         pathGeometry.Figures.Add(figure);
                         path.Data = pathGeometry;
                         path.Stroke = Brushes.White;
                         path.StrokeThickness = 1;
                         this.mainWindow.myCanvas.Children.Add(path);
                         break;
                     case 3:

                         break;
                     case 4:
                         break;
                     case 5://Polyline2D
                         startPoint = new Point(Convert.ToInt32(item.Polylines[0].X), -Convert.ToInt32(item.Polylines[0].Y));
                         double Bulge = item.Polylines[0].Bulge;
                         pathGeometry = new PathGeometry();
                         pathFigure = new PathFigure();
                         pathFigure.StartPoint = startPoint;
                         endPoint = new Point();
                         prePoint = startPoint;
                         double radius = item.Polylines[0].Radius;
                         PathSegment segment;
                         //循环各点连接成图形
                         for (int i = 1; i < item.Polylines.Count; i++)
                         {
                             endPoint = new Point(Convert.ToInt32(item.Polylines[i].X), -Convert.ToInt32(item.Polylines[i].Y));
                             segment = GetSegment(endPoint, Bulge, radius);
                             pathFigure.Segments.Add(segment);
                             radius = item.Polylines[i].Radius;
                             Bulge = item.Polylines[i].Bulge;
                             prePoint = endPoint;
                         }
                         //最后坐标连接首个坐标,完成闭合
                         segment = GetSegment(startPoint, Bulge, radius);
                         pathFigure.Segments.Add(segment);
                         pathGeometry.Figures.Add(pathFigure);
                         path = new Path
                         {
                             Stroke = Brushes.White,
                             StrokeThickness = 1,
                             Data = pathGeometry
                         };
                         this.mainWindow.myCanvas.Children.Add(path);
                         break;
                     default:
                         break;
                 }
             }
         }
         catch (Exception ex)
         {
         }
     }

     /// <summary>
     /// 获取Segment
     /// </summary>
     /// <param name="messageData"></param>
     /// <param name="StartPoint"></param>
     /// <param name="Bulge"></param>
     /// <returns></returns>
     private PathSegment GetSegment(Point point, double Bulge,double radius)
     {
         PathSegment pathSegment = null;
         try
         {
             if (Bulge == 0)
             {
                 pathSegment = new LineSegment(point, true);
             }
             else
             {
                 bool IsLargeArc = false;
                 SweepDirection sweepDirection = SweepDirection.Counterclockwise;
                 sweepDirection = SweepDirection.Counterclockwise;
                 //大于1优弧
                 IsLargeArc = Math.Abs(Bulge) > 1;
                 if (Bulge < 0)
                 {
                     //小于0顺时针
                     sweepDirection = SweepDirection.Clockwise;
                 }
                 pathSegment = new ArcSegment(point, new Size(radius, radius), 0, IsLargeArc, sweepDirection, true);
             }
         }
         catch (Exception ex)
         {
         }
         return pathSegment;
     }

效果如图所示:
在这里插入图片描述