GDI+ 绘制砂岩含量图版

来源:互联网 发布:淘宝助理上传宝贝失败 编辑:程序博客网 时间:2024/04/30 09:14

图版是在工作中经常会使用到的工具,它能够大大提高我们日常工作效率。地质图版在地质工作中具有举足轻重的作用,不仅可以轻松判断岩性,也可以依据经验图版直接得到结果,十分方便。

本程序目的绘制出一个地质常用三角图版:砂岩含量图版。图版的每个角代表每种含量,目标图版如下:

程序源代码下载地址见文章末尾。

图片1


首先建立一个TrianglePlate类。确定TrianglePlate类的属性两个:三角形中心(Center)和三角形边长(SideLength)。

复制代码
/// <summary>/// 三角形图版内心/// </summary>public PointF Center { set; get; }/// <summary>/// 三角形图版边长/// </summary>public float SideLength { get; set; }
复制代码

定义一个PointF数组代表三角形图版三个点的具体坐标,采用PointF类型的原因是PointF比Point更加精确,能够保证图像的精度。为了对类进行封装,坐标数组采用private类型。

private PointF[] _points;

TrianglePlate类的构造函数如下:

复制代码
public TrianglePlate(PointF center, float sidelength){     this.Center = center;     this.SideLength = sidelength;     this.Scale = sacle;     //计算三个点     _points = new PointF[3];     _points[0] = new PointF(this.Center.X - this.SideLength/2,                           (float) (this.Center.Y - this.SideLength/(2*Math.Sqrt(3)))           );    _points[1] = new PointF(this.Center.X + this.SideLength/2,                           (float) (this.Center.Y - this.SideLength/(2*Math.Sqrt(3)))           );    _points[2] = new PointF(this.Center.X,                           (float) (this.Center.Y - 2*this.SideLength/(Math.Sqrt(3)))           );}
复制代码

为了更好绘制图形,向TrianglePlate类加入DrawTrianglePlate方法,方便图形的绘制。

复制代码
/// <summary>/// 绘制三角形图版/// </summary>public void DrawTrianglePlate (Graphics g){    DrawSildes (g);}/// <summary>/// 绘制三角形图版三边/// </summary>private void DrawSildes (Graphics g){    g.DrawLine (this.SidePen, _points[0], _points[1]);    g.DrawLine (this.SidePen, _points[1], _points[2]);    g.DrawLine (this.SidePen, _points[2], _points[0]);}
复制代码

在From进行TrianglePlate初始化后,就可以调用Form的Paint函数进行绘制了。

复制代码
public FrmMain(){    InitializeComponent();    tp.SidePen = new Pen (Color.Black, 3);    tp.SidePen.StartCap = LineCap.Round;    tp.SaclePen = new Pen (Color.Black, 3);}TrianglePlate tp = new TrianglePlate (new PointF (200, 500), 350);private void tabPage1_Paint (object sender, PaintEventArgs e){    Graphics g = e.Graphics;    tp.DrawTrianglePlate (g, pcoursor);    myBuffer.Render (e.Graphics);    g.Dispose();    myBuffer.Dispose(); //释放资源}
复制代码

一个简单的三角形就绘制完成了,如下:

捕获


接下来进行绘制三角形图版的倾斜刻度线,定义一个float数组Scale用来存储刻度值,方便使用。定义一个PointF数组_scalepoints用来存储刻度线与三角形边框相交的点。

public float[] Scale { get; set; }private PointF[] _scalepoints;

对Scale和_scalepoints的初始化操作放在构造函数DrawTrianglePlate中。修改后的构造函数如下:

复制代码
public TrianglePlate (PointF center, float sidelength, float[] sacle){    this.Center = center;    this.SideLength = sidelength;    this.Scale = sacle;    //计算三个点    _points = new PointF[3];    _points[0] = new PointF (this.Center.X - this.SideLength / 2,                             (float) (this.Center.Y - this.SideLength / (2 * Math.Sqrt (3) ) )                            );    _points[1] = new PointF (this.Center.X + this.SideLength / 2,                             (float) (this.Center.Y - this.SideLength / (2 * Math.Sqrt (3) ) )                            );    _points[2] = new PointF (this.Center.X,                             (float) (this.Center.Y - 2 * this.SideLength / (Math.Sqrt (3) ) )                            );    //计算刻度点    _scalepoints = new PointF[12];    _scalepoints[0] = new PointF (_points[0].X + sidelength * this.Scale[0], _points[0].Y);    _scalepoints[1] = new PointF (_points[0].X + sidelength * this.Scale[1], _points[0].Y);    _scalepoints[2] = new PointF (_points[0].X + sidelength * (1 - this.Scale[1]), _points[0].Y);    _scalepoints[3] = new PointF (_points[0].X + sidelength * (1 - this.Scale[0]), _points[0].Y);    _scalepoints[4] = new PointF (_points[2].X - (float) (sidelength / 2) * this.Scale[0],                                  _points[2].Y + (float) (sidelength * Math.Sqrt (3) / 2) * this.Scale[0]);    _scalepoints[5] = new PointF (_points[2].X - (float) (sidelength / 2) * this.Scale[1],                                  _points[2].Y + (float) (sidelength * Math.Sqrt (3) / 2) * this.Scale[1]);    _scalepoints[6] = new PointF (_points[2].X + (float) (sidelength / 2) * this.Scale[0],                                  _points[2].Y + (float) (sidelength * Math.Sqrt (3) / 2) * this.Scale[0]);    _scalepoints[7] = new PointF (_points[2].X + (float) (sidelength / 2) * this.Scale[1],                                  _points[2].Y + (float) (sidelength * Math.Sqrt (3) / 2) * this.Scale[1]);    _scalepoints[8] = new PointF (_points[2].X,                                  _points[1].Y - (0.5f - this.Scale[0]) * this.SideLength * (float) Math.Sqrt (3) );    _scalepoints[11] = new PointF (_points[2].X,                                   _points[1].Y - (0.5f - this.Scale[1]) * this.SideLength * (float) Math.Sqrt (3) );    _scalepoints[9] =        new PointF (_scalepoints[8].X - (_scalepoints[11].Y - _scalepoints[8].Y) / 2 / (float) Math.Sqrt (3),                    (_scalepoints[8].Y + _scalepoints[11].Y) / 2);    _scalepoints[10] =        new PointF (_scalepoints[8].X + (_scalepoints[11].Y - _scalepoints[8].Y) / 2 / (float) Math.Sqrt (3),                    (_scalepoints[8].Y + _scalepoints[11].Y) / 2);}
复制代码

加入DrawScale函数绘制刻度线,并在DrawTrianglePlate绘制函数进行调用。

复制代码
private void DrawScale (Graphics g){    g.DrawLine (this.SaclePen, _scalepoints[0], _scalepoints[6]);    g.DrawLine (this.SaclePen, _scalepoints[1], _scalepoints[7]);    g.DrawLine (this.SaclePen, _scalepoints[2], _scalepoints[5]);    g.DrawLine (this.SaclePen, _scalepoints[3], _scalepoints[4]);}
复制代码

接下来对图版的刻度和文字进行绘制。

复制代码
private void DrawTag (Graphics g){    g.DrawString ("长石", new Font ("宋体", 11), Brushes.Black, new PointF (_points[0].X - 25f, _points[0].Y - 25f) );    g.DrawString ("岩屑", new Font ("宋体", 11), Brushes.Black, new PointF (_points[1].X + 5f, _points[1].Y - 25f) );    g.DrawString ("石英", new Font ("宋体", 11), Brushes.Black, new PointF (_points[2].X - 25f, _points[2].Y - 15f) );    g.DrawString ( (100 - this.Scale[0] * 100).ToString(), new Font ("宋体", 11), Brushes.Black,                   new PointF (_scalepoints[0].X, _scalepoints[0].Y + 3) );    g.DrawString ( (100 - this.Scale[1] * 100).ToString(), new Font ("宋体", 11), Brushes.Black,                   new PointF (_scalepoints[1].X, _scalepoints[1].Y + 3) );    g.DrawString ( (this.Scale[1] * 100).ToString(), new Font ("宋体", 11), Brushes.Black,                   new PointF (_scalepoints[2].X, _scalepoints[2].Y + 3) );    g.DrawString ( (this.Scale[0] * 100).ToString(), new Font ("宋体", 11), Brushes.Black,                   new PointF (_scalepoints[3].X, _scalepoints[3].Y + 3) );    g.DrawString ( (this.Scale[0] * 100).ToString(), new Font ("宋体", 11), Brushes.Black,                   new PointF (_scalepoints[4].X - 25f, _scalepoints[4].Y - 5) );    g.DrawString ( (this.Scale[1] * 100).ToString(), new Font ("宋体", 11), Brushes.Black,                   new PointF (_scalepoints[5].X - 25f, _scalepoints[5].Y - 5) );    g.DrawString ( (this.Scale[0] * 100).ToString(), new Font ("宋体", 11), Brushes.Black,                   new PointF (_scalepoints[6].X + 5f, _scalepoints[6].Y - 5) );    g.DrawString ( (this.Scale[1] * 100).ToString(), new Font ("宋体", 11), Brushes.Black,                   new PointF (_scalepoints[7].X + 5f, _scalepoints[7].Y - 5) );}
复制代码

DrawTag函数在DrawTrianglePlate绘制函数中进行调用,此时形成图形如下:

捕获捕获


接下来是最后一步,绘制随鼠标移动的动态刻度线。目的实现结果如下:

sa

为此,首先需要判断鼠标是否点在图版内,并获得鼠标的位置。向DrawTriangle类添加成员函数MouseIsIn。其中tpgp是一个GraphicsPath类型的变量,利用GraphicsPath提供的IsVisible函数判断鼠标是否在Path内。

复制代码
public bool MouseIsIn (Graphics g, PointF pt){    if (tpgp.IsVisible (pt) )    {        DrawDotDial (g, pt);        return true;    }    else        return false;}
复制代码

然后根据鼠标点与已知的刻度点计算得出动态刻度点坐标。

复制代码
private void DrawDotDial (Graphics g, PointF pt){    _dials = new PointF[6];    float py = _points[0].Y - pt.Y;    float px = pt.X - _points[0].X;    _dials[0] = new PointF (pt.X - py / (float) Math.Sqrt (3), _points[0].Y);    _dials[1] = new PointF (pt.X + py / (float) Math.Sqrt (3), _points[0].Y);    _dials[2] = new PointF ( (_dials[1].X + _points[0].X) / 2,                             _dials[0].Y - (_dials[1].X - _points[0].X) * (float) Math.Sqrt (3) / 2);    _dials[4] = new PointF ( (_points[1].X + _dials[0].X) / 2,                             _points[1].Y - (_points[1].X - _dials[0].X) * (float) Math.Sqrt (3) / 2);    _dials[3] = new PointF (_points[0].X + py / (float) Math.Sqrt (3),                            pt.Y);    _dials[5] = new PointF (_points[1].X - (_dials[3].X - _points[0].X),                            pt.Y);    Pen tmpen = new Pen (Color.Black, 1);    tmpen.DashStyle = DashStyle.Dash;    g.DrawLine (tmpen, _dials[0], _dials[4]);    g.DrawLine (tmpen, _dials[1], _dials[2]);    g.DrawLine (tmpen, _dials[3], _dials[5]);}
复制代码

然后在DrawTrianglePlate函数内对DrawDotDial进行调用,就完成了。


完整代码如下:

复制代码
using System;using System.Collections.Generic;using System.Linq;using System.Text;using System.Drawing;using System.Drawing.Drawing2D;namespace Ch_地质图版{    class TrianglePlate    {        public TrianglePlate(PointF center, float sidelength, float[] sacle)        {            this.Center = center;            this.SideLength = sidelength;            this.Scale = sacle;            //计算三个点            _points = new PointF[3];            _points[0] = new PointF(this.Center.X - this.SideLength/2,                                    (float) (this.Center.Y - this.SideLength/(2*Math.Sqrt(3)))                );            _points[1] = new PointF(this.Center.X + this.SideLength/2,                                    (float) (this.Center.Y - this.SideLength/(2*Math.Sqrt(3)))                );            _points[2] = new PointF(this.Center.X,                                    (float) (this.Center.Y - 2*this.SideLength/(Math.Sqrt(3)))                );            //计算刻度点            _scalepoints = new PointF[12];            _scalepoints[0] = new PointF(_points[0].X + sidelength * this.Scale[0], _points[0].Y);            _scalepoints[1] = new PointF(_points[0].X + sidelength * this.Scale[1], _points[0].Y);            _scalepoints[2] = new PointF(_points[0].X + sidelength * (1 - this.Scale[1]), _points[0].Y);            _scalepoints[3] = new PointF(_points[0].X + sidelength * (1 - this.Scale[0]), _points[0].Y);            _scalepoints[4] = new PointF(_points[2].X - (float)(sidelength / 2) * this.Scale[0],                                         _points[2].Y + (float)(sidelength * Math.Sqrt(3) / 2) * this.Scale[0]);            _scalepoints[5] = new PointF(_points[2].X - (float)(sidelength / 2) * this.Scale[1],                                         _points[2].Y + (float)(sidelength * Math.Sqrt(3) / 2) * this.Scale[1]);            _scalepoints[6] = new PointF(_points[2].X + (float)(sidelength / 2) * this.Scale[0],                                         _points[2].Y + (float)(sidelength * Math.Sqrt(3) / 2) * this.Scale[0]);            _scalepoints[7] = new PointF(_points[2].X + (float)(sidelength / 2) * this.Scale[1],                                         _points[2].Y + (float)(sidelength * Math.Sqrt(3) / 2) * this.Scale[1]);            _scalepoints[8] = new PointF(_points[2].X,                                         _points[1].Y - (0.5f - this.Scale[0]) * this.SideLength * (float)Math.Sqrt(3));            _scalepoints[11] = new PointF(_points[2].X,                                          _points[1].Y - (0.5f - this.Scale[1]) * this.SideLength * (float)Math.Sqrt(3));            _scalepoints[9] =                new PointF(_scalepoints[8].X - (_scalepoints[11].Y - _scalepoints[8].Y) / 2 / (float)Math.Sqrt(3),                           (_scalepoints[8].Y + _scalepoints[11].Y) / 2);            _scalepoints[10] =                new PointF(_scalepoints[8].X + (_scalepoints[11].Y - _scalepoints[8].Y) / 2 / (float)Math.Sqrt(3),                           (_scalepoints[8].Y + _scalepoints[11].Y) / 2);            tpgp = new GraphicsPath();            tpgp.AddLines(_points);            //DrawDotDial()        }        /// <summary>        /// 三角形图版内心        /// </summary>        public PointF Center { set; get; }        /// <summary>        /// 三角形图版边长        /// </summary>        public float SideLength { get; set; }        /// <summary>        /// 三角形图版画边笔        /// </summary>        public Pen SidePen { get; set; }        public Pen SaclePen { get; set; }        public float[] Scale { get; set; }        private PointF[] _points;        private PointF[] _scalepoints;        private GraphicsPath tpgp;        private PointF[] _dials;        public void DrawTrianglePlate(Graphics g,PointF tms)        {            DrawSildes(g);            DrawScale(g);            DrawTag(g);            if(!tms.IsEmpty)                    DrawDotDial(g, tms);        }        private void DrawSildes(Graphics g)        {            g.DrawLine(this.SidePen, _points[0], _points[1]);            g.DrawLine(this.SidePen, _points[1], _points[2]);            g.DrawLine(this.SidePen, _points[2], _points[0]);        }        private void DrawScale(Graphics g)        {            g.DrawLine(this.SaclePen, _scalepoints[0], _scalepoints[6]);            g.DrawLine(this.SaclePen, _scalepoints[1], _scalepoints[7]);            g.DrawLine(this.SaclePen, _scalepoints[2], _scalepoints[5]);            g.DrawLine(this.SaclePen, _scalepoints[3], _scalepoints[4]);        }        private void DrawTag(Graphics g)        {            //g.DrawString("①", new Font("楷体", 12), Brushes.Purple, _scalepoints[4].X, _scalepoints[4].Y);            //g.DrawString("②", new Font("楷体", 12), Brushes.Purple, _scalepoints[5].X, _scalepoints[5].Y);            //g.DrawString("③", new Font("楷体", 12), Brushes.Purple, _scalepoints[6].X, _scalepoints[6].Y);            //g.DrawLine(Pens.Black, _scalepoints[8], _scalepoints[11]);            //g.DrawLine(Pens.Black, _scalepoints[9], _scalepoints[10]);            //GraphicsPath gp = new GraphicsPath();            //gp.AddLines(new PointF[] {_scalepoints[4], _scalepoints[8], _scalepoints[6], _points[2]});            //g.FillPath(Brushes.Red, gp);            //gp = new GraphicsPath();            //gp.AddLines(new PointF[] { _scalepoints[4], _scalepoints[5], _scalepoints[9], _scalepoints[8] });            //g.FillPath(Brushes.Purple, gp);            //gp = new GraphicsPath();            //gp.AddLines(new PointF[] { _scalepoints[6], _scalepoints[8], _scalepoints[10], _scalepoints[7] });            //g.FillPath(Brushes.Pink, gp);            //gp = new GraphicsPath();            //gp.AddLines(new PointF[] { _scalepoints[8], _scalepoints[9], _scalepoints[11], _scalepoints[10] });            //g.FillPath(Brushes.RoyalBlue, gp);            //gp = new GraphicsPath();            //gp.AddLines(new PointF[] { _scalepoints[5], _scalepoints[9], _scalepoints[0], _points[0] });            //g.FillPath(Brushes.SkyBlue, gp);            //gp = new GraphicsPath();            //gp.AddLines(new PointF[] { _scalepoints[9], _scalepoints[11], _scalepoints[1], _scalepoints[0] });            //g.FillPath(Brushes.Green, gp);            //gp = new GraphicsPath();            //gp.AddLines(new PointF[] { _scalepoints[11], _scalepoints[10], _scalepoints[3], _scalepoints[2] });            //g.FillPath(Brushes.Yellow, gp);            //gp = new GraphicsPath();            //gp.AddLines(new PointF[] { _scalepoints[3], _scalepoints[10], _scalepoints[7], _points[1] });            //g.FillPath(Brushes.Tomato, gp);            g.DrawString("长石", new Font("宋体", 11), Brushes.Black, new PointF(_points[0].X - 25f, _points[0].Y - 25f));            g.DrawString("岩屑", new Font("宋体", 11), Brushes.Black, new PointF(_points[1].X + 5f, _points[1].Y - 25f));            g.DrawString("石英", new Font("宋体", 11), Brushes.Black, new PointF(_points[2].X - 25f, _points[2].Y - 15f));            g.DrawString((100 - this.Scale[0]*100).ToString(), new Font("宋体", 11), Brushes.Black,                         new PointF(_scalepoints[0].X, _scalepoints[0].Y+3));            g.DrawString((100 - this.Scale[1] * 100).ToString(), new Font("宋体", 11), Brushes.Black,                         new PointF(_scalepoints[1].X, _scalepoints[1].Y+3));            g.DrawString((this.Scale[1] * 100).ToString(), new Font("宋体", 11), Brushes.Black,                         new PointF(_scalepoints[2].X, _scalepoints[2].Y+3));            g.DrawString((this.Scale[0] * 100).ToString(), new Font("宋体", 11), Brushes.Black,                         new PointF(_scalepoints[3].X, _scalepoints[3].Y+3));            g.DrawString((this.Scale[0] * 100).ToString(), new Font("宋体", 11), Brushes.Black,                         new PointF(_scalepoints[4].X-25f, _scalepoints[4].Y-5));            g.DrawString((this.Scale[1] * 100).ToString(), new Font("宋体", 11), Brushes.Black,                         new PointF(_scalepoints[5].X - 25f, _scalepoints[5].Y - 5));            g.DrawString((this.Scale[0] * 100).ToString(), new Font("宋体", 11), Brushes.Black,                         new PointF(_scalepoints[6].X+5f, _scalepoints[6].Y - 5));            g.DrawString((this.Scale[1] * 100).ToString(), new Font("宋体", 11), Brushes.Black,                         new PointF(_scalepoints[7].X + 5f, _scalepoints[7].Y - 5));        }        public bool MouseIsIn(Graphics g, PointF pt)        {            if (tpgp.IsVisible(pt))            {                DrawDotDial(g, pt);                return true;            }                            else                return false;        }        private void DrawDotDial(Graphics g,PointF pt)        {            _dials = new PointF[6];            float py = _points[0].Y - pt.Y;            float px = pt.X - _points[0].X;            _dials[0] = new PointF(pt.X - py/(float) Math.Sqrt(3), _points[0].Y);            _dials[1] = new PointF(pt.X + py/(float) Math.Sqrt(3), _points[0].Y);            _dials[2] = new PointF((_dials[1].X + _points[0].X)/2,                                  _dials[0].Y - (_dials[1].X - _points[0].X)*(float) Math.Sqrt(3)/2);            _dials[4] = new PointF((_points[1].X + _dials[0].X)/2,                                  _points[1].Y - (_points[1].X - _dials[0].X) * (float)Math.Sqrt(3) / 2);            _dials[3] = new PointF(_points[0].X + py / (float)Math.Sqrt(3),                                  pt.Y);            _dials[5] = new PointF(_points[1].X-(_dials[3].X-_points[0].X),                                  pt.Y);            Pen tmpen = new Pen(Color.Black, 1);            tmpen.DashStyle = DashStyle.Dash;            g.DrawLine(tmpen, _dials[0], _dials[4]);            g.DrawLine(tmpen, _dials[1], _dials[2]);            g.DrawLine(tmpen, _dials[3], _dials[5]);            //GetContentScale(pt);            //g.DrawLine(tmpen,pt, new Point(0, 0));        }        private float[] GetContentScale(PointF pt)        {            float[] content = new float[3];            content[0] = (_dials[1].X - _points[0].X)/this.SideLength;            content[1] = (_points[1].X - _dials[0].X) / this.SideLength;            //content[1] = content[1]/this.SideLength/this.SideLength;            content[2] = Math.Abs(_points[2].X - _dials[0].X) * Math.Abs(_points[2].X - _dials[0].X) +                         Math.Abs(_points[2].Y - _dials[0].Y) * Math.Abs(_points[2].Y - _dials[0].Y);            content[2] = content[2] / this.SideLength / this.SideLength;            //content[1] = Math.Sqrt((double)content[1]);            //Math.Sqrt((double)(Math.Abs(_points[2].X - _dials[3].X)*Math.Abs(_points[2].X - _dials[3].X)) +            //          (double)(Math.Abs(_points[2].Y - _dials[3].Y)*Math.Abs(_points[2].Y - _dials[3].Y)            //          ))/this.SideLength;            return content;        }        public string GetScaleDes(PointF pt)        {            GraphicsPath gptmp = new GraphicsPath();            gptmp.AddLines(new PointF[] {_points[2], _scalepoints[4], _scalepoints[8], _scalepoints[6]});            if (gptmp.IsVisible(pt))                return "石英砂岩";            gptmp.AddLines(new PointF[] { _scalepoints[4], _scalepoints[5], _scalepoints[9], _scalepoints[8] });            if (gptmp.IsVisible(pt))                return "长石石英砂岩";            gptmp.AddLines(new PointF[] { _scalepoints[8], _scalepoints[9], _scalepoints[11], _scalepoints[10] });            if (gptmp.IsVisible(pt))                return "长石岩屑质石英砂岩";            gptmp.AddLines(new PointF[] { _scalepoints[6], _scalepoints[7], _scalepoints[9], _scalepoints[10] });            if (gptmp.IsVisible(pt))                return "岩屑石英砂岩";            gptmp.AddLines(new PointF[] { _scalepoints[5], _scalepoints[9], _scalepoints[0], _points[0] });            if (gptmp.IsVisible(pt))                return "长石砂岩";            gptmp.AddLines(new PointF[] { _scalepoints[9], _scalepoints[0], _scalepoints[1], _scalepoints[11] });            if (gptmp.IsVisible(pt))                return "碎屑质长石砂岩";            gptmp.AddLines(new PointF[] { _scalepoints[1], _scalepoints[2],  _scalepoints[11] });            if (gptmp.IsVisible(pt))                return "混合砂岩";            gptmp.AddLines(new PointF[] { _scalepoints[10], _scalepoints[11], _scalepoints[2], _scalepoints[3] });            if (gptmp.IsVisible(pt))                return "长石质岩屑砂岩";            gptmp.AddLines(new PointF[] { _scalepoints[7], _scalepoints[11], _scalepoints[3], _points[1] });            if (gptmp.IsVisible(pt))                return "岩屑砂岩";            return "";        }    }}
复制代码

程序源代码地址:http://pan.baidu.com/s/1osgAU

学习知识的好方法是看书、写博客,与他人分享知识和感想。
原创粉丝点击