[C# 学习笔记]运用 GDI+ 的 Matrix 进行显示图形的平移和缩放
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 进行显示图形的平移和缩放的更多相关文章
- 【Qt官方例程学习笔记】Analog Clock Window Example (画笔的平移/旋转/缩放应用)
这个例子演示了如何使用QPainter的转换和缩放特性来简化绘图. 值得学习的: 定时器事件ID检查: 在定时器事件中检查定时器id是比较好的实践. QPainter抗锯齿: We call QPai ...
- deepin linux学习笔记(四)进不去图形界面怎么办?
目录 deepin linux学习笔记(四)进不去图形界面怎么办? 前言 更换成lxde桌面 进不去图形界面怎么办? 总结 deepin linux学习笔记(四)进不去图形界面怎么办? 前言 生命不息 ...
- Android学习笔记进阶八之Matrix矩阵
Matrix,中文里叫矩阵,高等数学里有介绍,在图像处理方面,主要是用于平面的缩放.平移.旋转等操作. 在Android里面,Matrix由9个float值构成,是一个3*3的矩阵.最好记住.如下图: ...
- Dynamic CRM 2015学习笔记(2)更改系统显示语言
默认装的是英文的系统,想换成中文的.下面列出操作步骤: 1. 下载并安装语言包 http://www.microsoft.com/en-US/download/details.aspx?id=4501 ...
- canvas学习笔记(下篇) -- canvas入门教程--保存状态/变形/旋转/缩放/矩阵变换/综合案例(星空/时钟/小球)
[下篇] -- 建议学习时间4小时 课程共(上中下)三篇 此笔记是我初次接触canvas的时候的学习笔记,这次特意整理为博客供大家入门学习,几乎涵盖了canvas所有的基础知识,并且有众多练习案例, ...
- [原创]java WEB学习笔记30:Cookie Demo 之显示最近浏览的记录
本博客为原创:综合 尚硅谷(http://www.atguigu.com)的系统教程(深表感谢)和 网络上的现有资源(博客,文档,图书等),资源的出处我会标明 本博客的目的:①总结自己的学习过程,相当 ...
- JavaWeb和WebGIS学习笔记(五)——使用OpenLayers显示地图
系列链接: Java web与web gis学习笔记(一)--Tomcat环境搭建 Java web与web gis学习笔记(二)--百度地图API调用 JavaWeb和WebGIS学习笔记(三)-- ...
- CSS3学习笔记--transform中的Matrix(矩阵)
transform: matrix(a,b,c,d,e,f) ,如下图矩阵所示,任意点(x,y,1)经过matrix变化为(ax+cy+e,bx+dy+f,1),由此可以知道,matrix参数与tra ...
- Android学习笔记进阶九之Matrix对称变换
网上很多的倒影特效实际上就是一个对称变换,在改变透明度即可. Matrix对称变换包括很多种,有关于Y轴对称,关于X轴对称,关于y= -x对称等等. 1 关于Y轴对称 // 获取资源文件的引用res ...
- Android学习笔记进阶十之Matrix错切变换
刚开始我也不懂啥叫错切变换,一看效果图你就恍然大悟. 对图像的错切变换做个总结: x = x0 + b*y0; y = d*x0 + y0; 与之对应的方法是: Matrix matrix = new ...
随机推荐
- C#当窗体大小改变时,窗体中的控件大小也随之改变
第一种:推荐 在窗体中加上如下代码即可实现,但窗体点击放大按钮时却不能改变控件大小. private Size beforeResizeSize = Size.Empty;protectedoverr ...
- mariadb数据库查询(select)
查询基本使用(条件,排序,聚合函数,分组,分页) 示例:--创建学生表 create table students ( id int unsigned not null auto_increment ...
- vue 移动端px转rem
1.安装lib-flexible 终端执行命令:npm i lib-flexible --save 2.在main.js引入lib-flexible 3.终端执行命令:npm install post ...
- ue项目--浏览器出现卡顿及崩溃的原因查找与解决方案
一些内存泄露的情况进行了排查 全局变量 定时器 使用未销毁的全局事件和第三方库 v-if和v-show不合理使用,v-if和v-for不合理使用 使用watch
- pgsql给表字段设置默认值及设置主键
ALTER TABLE pavement_damage_dtl_temp add PRIMARY key(id); ALTER table pavement_damage_dtl_temp alter ...
- 学习lua-04,json.util merge方法对集合处理的实际应用,及tostring方法
local jsonutil = require("json.util") local merge = require("json.util").merge l ...
- Mac 卸载 Anaconda3
终端安装anaconda-clean conda install anaconda-clean 删除所有与 Anaconda 有关的文件与目录 anaconda-clean --yes 第 2 步中的 ...
- IIS10.0 Web平台安装程序无法安装URL重写工具
Windows10系统的IIS10.0需要安装URL rewrite重写模块2.0,提示"很遗憾,无法安装下列产品",解决方法: win键+R键,运行regedit,打开注册表编辑 ...
- 关于 java 上传,下载和导入报java.lang.IllegalStateException异常解决办法
java.lang.IllegalStateException异常解决办法 最近在使用response.sendRedirect()时出现如下错误:java.lang.IllegalStateExc ...
- 1.3 C语言--指针与结构体
指针 指针概念的引入 关于内存 程序有数据和指令组成,数据和指令在执行过程中存放在内存中.变量是程序数据中的一种,因此变量也存储在内存中:内存中的每个字节都有一个唯一的编码,即内存地址.32位机的内存 ...