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

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

1.下载安装netDxf库

2.读取dxf文件,数据存储到DataTable

using netDxf;

using netDxf.Entities;

///

/// 读取CAD的Dxf文件数据

///

public class DxfHelperHtility

{

///

/// 读取CAD文件数据

///

///

///

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;

}

///

/// 坐标转换

///

/// 坐标值

/// 用户原点坐标

///

private static int ToConver(double value,double ucs)

{

int result = 0;

result = (int)Math.Round(value- ucs);

return result;

}

///

/// 动态创建表格列

///

///

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;

}

///

/// 根据两点和凸度,计算半径

///

///

///

///

///

///

///

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数据转换成通用数据,供上层使用

///

/// 读取CAD文件数据

///

///

///

public static List ReadDxf(string path)

{

List list = new List();

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;

}

///

/// CAD图形实体类

///

public class DxfModel

{

///

/// 图形类型

/// 0:直线

/// 1:圆形

/// 2:圆弧

/// 3:文本

/// 4:椭圆

/// 5:Polyline2D

///

public int DrawingType;

///

/// 起点X坐标

///

public double StartPointX;

///

/// 起点Y坐标

///

public double StartPointY;

///

/// 终点X坐标

///

public double EndPointX;

///

/// 终点Y坐标

///

public double EndPointY;

///

/// 圆半径

///

public double Radius;

///

/// 起点角度

///

public double StartAngle;

///

/// 终点角度

///

public double EndAngle;

///

/// 椭圆长轴

///

public double MajorAxis;

///

/// 椭圆短轴

///

public double MinorAxis;

///

/// 线宽

///

public double Thickness;

///

/// 其他类型数据

///

public string Data;

///

/// Polyline数据

///

public List Polylines = new List();

}

///

/// Polyline 实体

///

public class Polyline

{

///

/// 坐标X

///

public double X;

///

/// 坐标Y

///

public double Y;

///

/// 凸度

///

public double Bulge;

public double StartWidth;

public double EndWidth;

///

/// 半径

///

public double Radius;

}

4.基于Canvas画图

///

/// 画图

///

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 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)

{

}

}

///

/// 获取Segment

///

///

///

///

///

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;

}

效果如图所示:

相关推荐

mil,mm与inch之间的转换

mil,mm与inch之间的转换

📅 10-08 👁️ 5844
《和平精英》空投刷新时间是多久 空投刷新时间说明
黑肖有哪些生肖,黑肖的命格

黑肖有哪些生肖,黑肖的命格

📅 07-08 👁️ 6784