1.下载安装netDxf库
2.读取dxf文件,数据存储到DataTable
csharp
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;
}
}
特别注意:如果用户画的图不是默认原点,而是自定义原点,需要获取用户坐标原点,其他线段点需要减去用户坐标原点才能得到正确的坐标
csharp
//获取用户坐标系(UCS)的原点坐标
netDxf.Tables.UCS ucs =dxf.DrawingVariables.CurrentUCS;
至此完成了dxf文件读取并将数据存储到DataTable,供后续处理。
3.DataTable数据转换成通用数据,供上层使用
csharp
/// <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画图
csharp
/// <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;
}
效果如图所示: