[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);
        }

 


免责声明!

本站转载的文章为个人学习借鉴使用,本站对版权不负任何法律责任。如果侵犯了您的隐私权益,请联系本站邮箱yoyou2525@163.com删除。



 
粤ICP备18138465号  © 2018-2025 CODEPRJ.COM