C# 学习中,想尝试着做一个工控方面的上位机,可以读取CAD绘制的图形,然后把它显示出来,后面让运动控制器去走CAD里面的轨迹。

一、用netDXF 开源包,对DXF文件进行解析。解析后的直线、圆、圆弧、椭圆、多段线、曲线等图纸,分别用List存起来。

   /// <summary>
/// 打开DXF文件
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private void btn_Open_Click(object sender, EventArgs e)
{ using (OpenFileDialog openFile = new OpenFileDialog())
{
openFile.Title = "加载DXF文件";
openFile.Filter = "dxf File(*.dxf)|*.dxf|ALL File(*.*)|*.*";
if (openFile.ShowDialog() == DialogResult.OK)
{
//获得文件路径
file = openFile.FileName;
//加载文件
dxf = DxfDocument.Load(file);
//解析文件
ImPort(file);
//生成绘制路径
BuildPath();
//绘制图形
this.MainPic.Image = PaintDXF(this.MainPic);
}
}
}
 /// <summary>
/// 解析DXF文件
/// </summary>
/// <param name="fileName">要解析的文件名</param>
public void ImPort(string fileName)
{
lineList.Clear();
arcList.Clear();
cirList.Clear();
polylineList.Clear();
polylines.Clear(); // 解析多段线
foreach (LwPolyline lwPolyline in dxf.LwPolylines)
{
bool isHaveArc = false;
lwPolylineVertices.Clear();
lwPolylineVertices.AddRange(lwPolyline.Vertexes);
foreach (LwPolylineVertex lwPolylineVertex in lwPolylineVertices)
{
if (lwPolylineVertex.Bulge != 0)
{
isHaveArc = true;
break;
}
}
if (isHaveArc)
{
entityObjList.Clear();
//将LwPolyline实体炸开
entityObjList.AddRange(lwPolyline.Explode());
//分解多段线集合
foreach (EntityObject entityObject in entityObjList)
{
//如果是直线,就填加到直线集合
Line line_Tmp = entityObject as Line;
if (line_Tmp != null)
{
lineList.Add(line_Tmp);
}
//如果是圆弧,就填加到圆弧集合
Arc arc_Tmp = entityObject as Arc;
if (arc_Tmp != null)
{
arcList.Add(arc_Tmp);
}
}
}
else //多段线中没有圆弧,就把这个多段线添加到多段线List中
{
polylineList.Add(lwPolyline);
}
}
//解析直线
foreach (Line ln in dxf.Lines)
{
lineList.Add(ln);
}
//解析圆弧
foreach (Arc arc in dxf.Arcs)
{
arcList.Add(arc);
}
//解析圆
foreach (Circle cir in dxf.Circles)
{
cirList.Add(cir);
}
//解析椭圆
foreach (Ellipse elp in dxf.Ellipses)
{
//把椭圆转换成多段线
int precision = GetEllipseToPolylinesPercision(elp, 0.5);
polylineList.Add(elp.ToPolyline(precision));
}
//解析样条曲线
foreach (Spline spline in dxf.Splines)
{
//将样条曲线转换成多段线 (用绘制多段线的方式绘制)
int precision = GetSplineToPolylinesPrecision(spline, 0.5);
polylines.Add(spline.ToPolyline(precision));
}
//视窗中心坐标
viewcCenterX = dxf.Viewport.ViewCenter.X;
viewcCenterY = dxf.Viewport.ViewCenter.Y;
//视窗高度
viewcCenterH = dxf.Viewport.ViewHeight;
//根据视窗高度和显示框高度调整图形显示比例
m_fratio = (float)(MainPic.Size.Height / viewcCenterH); //显示数据
this.uiDataGridView1.DataSource = lineList;
this.dataGridView2.DataSource = arcList;
this.dataGridView3.DataSource = cirList;
this.dataGridView4.DataSource = polylines;
}

二、 把所有需要绘制图形(直线、圆弧、圆、椭圆、多段线、曲线、等)都添加到GraphicsPath 对象里面去

/// <summary>
/// 生成绘制路径
/// </summary>
private void BuildPath()
{
//清空之前存在的路径轨迹
graphicsPath.Reset();
// 直线 添加到绘制路径中
foreach (Line line in lineList)
{
PointF tf = Vector2PointF(line.StartPoint);
PointF tf2 = Vector2PointF(line.EndPoint);
//将线段添加到绘制路径对象
graphicsPath_tmp.AddLine(tf, tf2);
graphicsPath.AddPath(graphicsPath_tmp, false);
graphicsPath_tmp.Reset();
}
// 圆弧 添加到绘制路径中
foreach (Arc arc in arcList)
{
RectangleF ef3 = new RectangleF();
//半径
float r = Convert.ToSingle(arc.Radius);//* m_fratio;
//圆心坐标转换
PointF pf = Vector2PointF(arc.Center);
ef3.X = pf.X - r;
ef3.Y = pf.Y - r;
ef3.Width = 2f * r;
ef3.Height = 2f * r;
//起始角度
starAg = Convert.ToSingle(arc.StartAngle);
//扫描角度
sweepAg = Convert.ToSingle((360 - arc.StartAngle + arc.EndAngle) % 360);
graphicsPath_tmp.AddArc(ef3, starAg, sweepAg);
graphicsPath.AddPath(graphicsPath_tmp, false);
graphicsPath_tmp.Reset();
}
// 圆 添加到绘制路径中
foreach (Circle circle in cirList)
{
RectangleF rect = new RectangleF();
float r = Convert.ToSingle(circle.Radius);
//显示坐标转换
PointF pf = Vector2PointF(circle.Center); rect.X = pf.X - r;
rect.Y = pf.Y - r;
rect.Width = 2f * r;
rect.Height = 2f * r;
graphicsPath_tmp.AddEllipse(rect);
graphicsPath.AddPath(graphicsPath_tmp, false);
graphicsPath_tmp.Reset();
}
// 样条曲线转成的多段线添加到绘制路径中
foreach (Polyline polyline in polylines)
{
pointFs.Clear();
foreach (PolylineVertex vertex in polyline.Vertexes)
{
PointF pf = Vector2PointF(vertex.Position);
pointFs.Add(pf);
}
PointF[] potFs = pointFs.ToArray();
graphicsPath_tmp.AddLines(potFs);
if (polyline.IsClosed)
{
graphicsPath_tmp.CloseFigure();
}
graphicsPath.AddPath(graphicsPath_tmp, false);
graphicsPath_tmp.Reset();
}
// 轻量多段线 添加到绘制路径中
foreach (LwPolyline lwPolyline in polylineList)
{
pointFs.Clear();
foreach (LwPolylineVertex vertex in lwPolyline.Vertexes)
{
PointF pf = Vector2PointF(vertex.Position);
pointFs.Add(pf);
}
PointF[] potFs = pointFs.ToArray();
graphicsPath_tmp.AddLines(potFs);
if (lwPolyline.IsClosed)
{
graphicsPath_tmp.CloseFigure();
}
graphicsPath.AddPath(graphicsPath_tmp, false);
graphicsPath_tmp.Reset();
}
//定义一个矩阵,把纵坐标翻转
Matrix matrix = new Matrix(1, 0, 0, -1, 0, 0);
//定义矩阵的缩放向量
matrix.Scale(m_fratio, m_fratio);
//定义矩阵偏移向量 dxf文件的视窗中心放到显示的中心
matrix.Translate((float)viewcCenterX * -1, (float)viewcCenterY * -1);
//对路径进行矩阵转换
graphicsPath.Transform(matrix);
}

三、绘制路径(显示图形)

 //新一个Matrix矩阵对象
Matrix translateMatrix = new Matrix(); /// <summary>
/// 图形绘制
/// </summary>
/// <param name="picture">绘制图形的控件</param>
/// <returns>返回图形绘制完成的图片</returns>
public Bitmap PaintDXF(PictureBox myPicBox)
{ //定义一个GDI+对象
using (Graphics graphics = Graphics.FromImage(image))
{
////设GDI对象的单位
//graphics.PageUnit = GraphicsUnit.Pixel;
// 设置为可剪辑区域
graphics.SetClip(displayRectangle);
//定义一个刷子 设置为黑色
SolidBrush brush = new SolidBrush(Color.Black);
//用上面定义的刷子填充整个图形
graphics.FillRectangle(brush, displayRectangle);
//定义绘制直线和曲线的笔 并设置为它的颜色和宽度(宽度为浮点数)
Pen pen1 = new Pen(Color.Blue, 2f);
Pen pen2 = new Pen(Color.FromArgb(50, 50, 50), 1f);
//画横格
for (int i = 1, rh = displayRectangle.Height; i < rh; i += 40)
{
graphics.DrawLine(pen2, 0, i, displayRectangle.Width, i);
}
//画竖格
for (int i = 1, rw = displayRectangle.Width; i < rw; i += 40)
{
graphics.DrawLine(pen2, i, 0, i, displayRectangle.Height);
}
//设置图形显示区中心为坐标原点
graphics.TranslateTransform(displayRectangle.Width / 2, displayRectangle.Height / 2);
//对绘制路径用定义的矩阵进行矩阵变换
graphicsPath.Transform(translateMatrix);
//绘制图象
graphics.DrawPath(pen1, graphicsPath);
} return image;
}

四、图形平移

   /// <summary>
/// 鼠标按下
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private void MainPic_MouseDown(object sender, MouseEventArgs e)
{
if (e.Button == MouseButtons.Left)
isLeftButton = true;
xStrat = e.X;
yStart = e.Y; }
   /// <summary>
/// 鼠标拖动
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private void MainPic_MouseMove(object sender, MouseEventArgs e)
{
if (isLeftButton == true)
{
xEnd = e.X;
yEnd = e.Y;
m13 = xEnd - xStrat;
m23 = yEnd - yStart;
//重置矩阵
translateMatrix.Reset();
// 定义矩阵平移向量。
translateMatrix.Translate(m13, m23);
MainPic.Image = PaintDXF(this.MainPic);
m13 = m23 = 0;
xStrat = xEnd;
yStart = yEnd;
}
}

五、图形缩放

/// <summary>
/// 滚轮滚动
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private void MainPic_MouseWheel(object sender, MouseEventArgs e)
{
float fratio = 1f;
if (e.Delta < 0)
{
m_fratio *= 1f-0.05f;
fratio -= 0.05f;
}
else
{
m_fratio *= 1f+0.05f;
fratio += 0.05f;
}
if (m_fratio >= 10f)
{
m_fratio = 10f;
fratio = 1f;
}
if (m_fratio <= 0.1f)
{
m_fratio = 0.1f;
fratio = 1f;
}
//重置矩阵
translateMatrix.Reset();
//定义矩阵缩放向量
translateMatrix.Scale(fratio, fratio);
MainPic.Image = PaintDXF(this.MainPic);
}

[C# 学习笔记]运用 GDI+ 的 Matrix 进行显示图形的平移和缩放的更多相关文章

  1. 【Qt官方例程学习笔记】Analog Clock Window Example (画笔的平移/旋转/缩放应用)

    这个例子演示了如何使用QPainter的转换和缩放特性来简化绘图. 值得学习的: 定时器事件ID检查: 在定时器事件中检查定时器id是比较好的实践. QPainter抗锯齿: We call QPai ...

  2. deepin linux学习笔记(四)进不去图形界面怎么办?

    目录 deepin linux学习笔记(四)进不去图形界面怎么办? 前言 更换成lxde桌面 进不去图形界面怎么办? 总结 deepin linux学习笔记(四)进不去图形界面怎么办? 前言 生命不息 ...

  3. Android学习笔记进阶八之Matrix矩阵

    Matrix,中文里叫矩阵,高等数学里有介绍,在图像处理方面,主要是用于平面的缩放.平移.旋转等操作. 在Android里面,Matrix由9个float值构成,是一个3*3的矩阵.最好记住.如下图: ...

  4. Dynamic CRM 2015学习笔记(2)更改系统显示语言

    默认装的是英文的系统,想换成中文的.下面列出操作步骤: 1. 下载并安装语言包 http://www.microsoft.com/en-US/download/details.aspx?id=4501 ...

  5. canvas学习笔记(下篇) -- canvas入门教程--保存状态/变形/旋转/缩放/矩阵变换/综合案例(星空/时钟/小球)

    [下篇] -- 建议学习时间4小时  课程共(上中下)三篇 此笔记是我初次接触canvas的时候的学习笔记,这次特意整理为博客供大家入门学习,几乎涵盖了canvas所有的基础知识,并且有众多练习案例, ...

  6. [原创]java WEB学习笔记30:Cookie Demo 之显示最近浏览的记录

    本博客为原创:综合 尚硅谷(http://www.atguigu.com)的系统教程(深表感谢)和 网络上的现有资源(博客,文档,图书等),资源的出处我会标明 本博客的目的:①总结自己的学习过程,相当 ...

  7. JavaWeb和WebGIS学习笔记(五)——使用OpenLayers显示地图

    系列链接: Java web与web gis学习笔记(一)--Tomcat环境搭建 Java web与web gis学习笔记(二)--百度地图API调用 JavaWeb和WebGIS学习笔记(三)-- ...

  8. CSS3学习笔记--transform中的Matrix(矩阵)

    transform: matrix(a,b,c,d,e,f) ,如下图矩阵所示,任意点(x,y,1)经过matrix变化为(ax+cy+e,bx+dy+f,1),由此可以知道,matrix参数与tra ...

  9. Android学习笔记进阶九之Matrix对称变换

    网上很多的倒影特效实际上就是一个对称变换,在改变透明度即可. Matrix对称变换包括很多种,有关于Y轴对称,关于X轴对称,关于y= -x对称等等. 1 关于Y轴对称 // 获取资源文件的引用res ...

  10. Android学习笔记进阶十之Matrix错切变换

    刚开始我也不懂啥叫错切变换,一看效果图你就恍然大悟. 对图像的错切变换做个总结: x = x0 + b*y0; y = d*x0 + y0; 与之对应的方法是: Matrix matrix = new ...

随机推荐

  1. pytorch 独热编码报错的解决办法:one_hot is only applicable to index tensor

    首先,报错原因,我认为是数据类型错误, 在文档中表示,第一个tensor参数的数据类型为LongTensor,也就是torch.int64类型的,如果你有报这个错:"one_hot is o ...

  2. winform 登录后跳转百度地图报错 使用委托解决

    最近用winform做一个登录后跳转到百度地图的小程序,使用了线程,winform的UI是单线程操作的,由于百度地图写在另外一个窗体,导致报错.后来使用了委托解决了这个小问题. delegate vo ...

  3. 【awk】找出两个文件中的不同值

    https://blog.csdn.net/weixin_33534991/article/details/116683524 awk 'NR==FNR{a[$0]}NR>FNR{ if(!($ ...

  4. keil 常用调试方法

    1.内存调试方法, 参考链接: https://blog.51cto.com/u_4029519/5423341 2.汇编调试方法 常用到bootlader和应用程序的调试 1.生成bin文件.汇编文 ...

  5. JS数组的交集与差集

    有两个数组arr1,arr2 实现arr2中去除arr1相同的元素 e.g arr1=[1,2,3] arr2=[2,3,4] ===> result = [4] 实现 获取两个数组(arr1, ...

  6. CentOS7 修改root密码

    能登录系统修改root密码 passwd root(可以是其他什么用户) 输入新密码(两次)   忘记root密码不能进入系统,修改root密码   1.开机进入grub界面按e进入单用户编辑模式 2 ...

  7. 【2020NOI.AC省选模拟#5】C. 光滑序列

    题目链接 原题解: 光滑的序列一定有长度为$K$的循环节. 使用动态规划,设$F(i,j)$为使前$i$个整数的和为$j$的最小修改次数. 记$cost(i,v)$为令$A_i,A_{i+K},A_{ ...

  8. Study python_02

    分支结构 简单的使用if语句 使用if-else import random# 调用一个随机数包(只看if的情况可忽略) n1 = random.randrange(100) n2 = random. ...

  9. pycharm 导入requests库踩坑帖

    requests库确认安装了,但是在pycharm里各种导入不了,简直要奔溃,后来看帖子,有博主"alt + enter"了一下,跳出了install选项,然后就可以了... 用个 ...

  10. session.timeout.ms、heartbeat.interval.ms、max.poll.interval.ms的含义及联系

    如果你使用消费者,那么一定会接触这几个参数: session.timeout.ms.heartbeat.interval.ms.max.poll.interval.ms,先让我们看看分别代表什么含义吧 ...