另外一个版本是使用OpenTK开发,文字显示效果不太理想,因此换了SharpGL重新写了一个。

文字是缓存为图片,然后使用坐标映射的方式绘制到图表上。

资源忘了复制链接,欢迎来白嫖

public partial class QChart : UserControl
    {

public QChart()
        {
            InitializeComponent();

BackColor = Color.White;
            LineColor = Color.Gray;
            DotColor = Color.Red;
            TitleColor = Color.Red;

TxtColor = Color.Black;

XTitle = "X";
            YTitle = "Y";
            ZTitle = "Z";
            XRange = 5;
            YRange = 3;
            ZRange = 3;
            _rotationy = 1;
            FontSize = 12;//文字大小
            minx = miny = minz = 0;
            maxx = maxy = maxz = 10;
            XStep = YStep = ZStep = 1;
          
        }

private int _x;
        private float _rotationx, _rotationy;

private float zIndex = 12;//俯视角度,好看

private bool locked = false;//是否锁定

private List<Point3D> points;

public float FontSize { get; set; }

/// <summary>
        /// 坐标线条颜色
        /// </summary>
        public Color LineColor { get; set; }
        /// <summary>
        /// 点颜色
        /// </summary>
        public Color DotColor { get; set; }
        /// <summary>
        /// 标题颜色
        /// </summary>
        public Color TitleColor { get; set; }
        /// <summary>
        /// 刻度颜色
        /// </summary>
        public Color TxtColor { get; set; }
        /// <summary>
        /// X轴标题
        /// </summary>
        public String XTitle { get; set; }
        /// <summary>
        /// Y轴标题
        /// </summary>
        public String YTitle { get; set; }
        /// <summary>
        /// Z轴标题
        /// </summary>
        public String ZTitle { get; set; }

public int XRange { get; set; }
        public int YRange { get; set; }
        public int ZRange { get; set; }
        public double maxx { get; set; }
        public double minx { get; set; }
        public double maxy { get; set; }
        public double miny { get; set; }
        public double maxz { get; set; }
        public double minz { get; set; }
        /// <summary>
        /// X方向的刻度间隔,默认1
        /// </summary>
        public int XStep { get; set; }
        /// <summary>
        /// y方向的刻度间隔,默认1
        /// </summary>
        public int YStep { get; set; }

/// <summary>
        /// Z方向的刻度间隔,默认1
        /// </summary>
        public int ZStep { get; set; }

private Point mouse = new Point();//记录鼠标位置

private void openGLControl1_OpenGLDraw(object sender, RenderEventArgs e)
        {
            //  Get the OpenGL object, just to clean up the code.
            OpenGL gl = this.openGLControl1.OpenGL;

gl.Clear(OpenGL.GL_COLOR_BUFFER_BIT | OpenGL.GL_DEPTH_BUFFER_BIT);

gl.ClearColor((float)(BackColor.R / 255.0), (float)(BackColor.G / 255.0), (float)(BackColor.B / 255.0), 1f);//背景色
            gl.Clear(OpenGL.GL_COLOR_BUFFER_BIT | OpenGL.GL_DEPTH_BUFFER_BIT | OpenGL.GL_STENCIL_BUFFER_BIT);

gl.MatrixMode(OpenGL.GL_MODELVIEW);

gl.LoadIdentity();

gl.Rotate(_rotationx, 1, 0, 0);//X轴旋转

gl.Rotate(_rotationy, 0, 1, 0);//Y轴旋转

//绘制坐标

gl.Color(LineColor.R, LineColor.G, LineColor.B);//线颜色

//gl.DrawText(0, 0, TitleColor, "宋体", FontSize, "ss");

//水平线,X面
            for (int i = -XRange; i <= XRange; i++)
            {
                gl.Begin(OpenGL.GL_LINES);
                gl.Vertex(i, -YRange, -ZRange);
                gl.Vertex(i, -YRange, ZRange);
                gl.End();

}
            for (int i = -ZRange; i <= ZRange; i++)
            {
                gl.Begin(OpenGL.GL_LINES);
                gl.Vertex(-XRange, -YRange, i);
                gl.Vertex(XRange, -YRange, i);
                gl.End();

}

//竖直线,Y面
            for (int i = -YRange; i <= YRange; i++)
            {
                gl.Begin(OpenGL.GL_LINES);
                gl.Vertex(-XRange, i, -ZRange);
                gl.Vertex(-XRange, i, ZRange);
                gl.End();
            }

for (int i = -ZRange; i <= ZRange; i++)
            {
                gl.Begin(OpenGL.GL_LINES);
                gl.Vertex(-XRange, -YRange, i);
                gl.Vertex(-XRange, YRange, i);
                gl.End();
            }
            //Z面
            for (int i = -YRange; i <= YRange; i++)
            {
                gl.Begin(OpenGL.GL_LINES);
                gl.Vertex(-XRange, i, -ZRange);
                gl.Vertex(XRange, i, -ZRange);
                gl.End();
            }

for (int i = -XRange; i <= XRange; i++)
            {
                gl.Begin(OpenGL.GL_LINES);
                gl.Vertex(i, -YRange, -ZRange);
                gl.Vertex(i, YRange, -ZRange);
                gl.End();
            }

if (XStep < 1) XStep = 1;
            //刻度x
            for (int i = -XRange; i <= XRange; i+=XStep)
            {

double v = (i + XRange) / (2.0 * XRange) * (maxx - minx);
                DrawText(String.Format("{0:f2}", v), i - 0.2f, -YRange - 0.5f, -ZRange - 0.2f, TxtColor);

}
            //DrawTextCN(XTitle, XRange + 0.5f, -YRange - 0.25f, -ZRange, TitleColor);
            if (YStep < 1) YStep = 1;
            //刻度Y
            for (int i = -YRange; i < YRange; i+= YStep)
            {
                double v = (i + YRange) / (2.0 * YRange) * (maxy - miny);
                DrawText(String.Format("{0:f2}", v), -XRange - 0.2f, i, -ZRange - 0.2f, TxtColor);
            }
           // DrawTextCN(YTitle, -XRange, YRange, -ZRange, TitleColor);

if (ZStep < 1) ZStep = 1;
            //刻度Z
            for (int i = -ZRange; i < ZRange; i+=ZStep)
            {
                double v = (i + ZRange) / (2.0 * YRange) * (maxz - minz);
                DrawText(String.Format("{0:f2}", v), -XRange - 0.5f, -YRange - 0.5f, i, TxtColor);
            }
           // DrawTextCN(ZTitle, -XRange, -YRange - 0.5f, ZRange + 0.5f, TitleColor);

//输出三个坐标标题
            gl.Color(TitleColor.R, TitleColor.G, TitleColor.B);
            drawCNString("  ", 99, 99, 99, gl);
            drawCNString(ZTitle, -XRange, -YRange,ZRange+0.5f,  gl);
            drawCNString(XTitle+0.5f , XRange, -YRange, -ZRange, gl);
            drawCNString(YTitle , -XRange, YRange+0.5f, -ZRange, gl);

//如果有点,才绘制点

if (points != null && points.Count > 0)
            {
                gl.Color(DotColor.R, DotColor.G, DotColor.B);

// gl.PointSize(4);

foreach (Point3D p in points)
                {
                    double x = XRange * (2 * (p.X - minx) / (maxx - minx) - 1);
                    double y = YRange * (2 * (p.Y - miny) / (maxy - miny) - 1);
                    double z = ZRange * (2 * (p.Z - minz) / (maxz - minz) - 1);
                    if (p.OnMouse) gl.PointSize(6);
                    else gl.PointSize(4);
                    gl.Begin(OpenGL.GL_POINTS);
                    gl.Vertex(x, y, z);
                    gl.End();
                }

// GL.DrawPixels

}

gl.Flush();
        }

private void DrawText(String s, double x, double y, double z, Color color)
        {
            OpenGL gl = this.openGLControl1.OpenGL;
            var sv = SharpGL.SceneGraph.OpenGLSceneGraphExtensions.Project(gl, new SharpGL.SceneGraph.Vertex((float)x, (float)y, (float)z));
            gl.DrawText((int)sv.X, (int)sv.Y, (float)(color.R / 255.0), (float)(color.G / 255.0), (float)(color.B / 255.0), "宋体", FontSize, s);

}

private void drawCNString(string str, float x, float y,float z, OpenGL gl)
        {

int i;

//  Create the font based on the face name.
            var hFont = Win32.CreateFont((int)FontSize+4, 0, 0, 0, Win32.FW_DONTCARE, 0, 0, 0, Win32.DEFAULT_CHARSET,
                Win32.OUT_OUTLINE_PRECIS, Win32.CLIP_DEFAULT_PRECIS, Win32.CLEARTYPE_QUALITY, Win32.CLEARTYPE_NATURAL_QUALITY, "宋体");

//  Select the font handle.
            var hOldObject = Win32.SelectObject(gl.RenderContextProvider.DeviceContextHandle, hFont);
            //  Create the list base.
            var list = gl.GenLists(1);

gl.RasterPos(x, y,z);

// 逐个输出字符
            for (i = 0; i < str.Length;i++)
            {
                bool result = Win32.wglUseFontBitmapsW(gl.RenderContextProvider.DeviceContextHandle, str[i], 1, list);
                gl.CallList(list);
            }
            // 回收所有临时资源
            //free(wstring);
            gl.DeleteLists(list, 1);
            //  Reselect the old font.
            Win32.SelectObject(gl.RenderContextProvider.DeviceContextHandle, hOldObject);
            //  Free the font.
            Win32.DeleteObject(hFont);
            //glDeleteLists(list, 1);
        }

/// <summary>
        /// 传入坐标集合
        /// </summary>
        /// <param name="points"></param>
        public void ShowPoints(List<Point3D> points)
        {
            this.points = points;
            if (points == null || points.Count == 0) return;

maxx = points[0].X;
            minx = points[0].X;
            maxy = points[0].Y;
            miny = points[0].Y;
            maxz = points[0].Z;
            minz = points[0].Z;

foreach (Point3D p in points)
            {
                if (p.X > maxx) maxx = p.X;
                if (p.X < minx) minx = p.X;
                if (p.Y > maxy) maxy = p.Y;
                if (p.Y < miny) miny = p.Y;
                if (p.Z > maxz) maxz = p.Z;
                if (p.Z < minz) minz = p.Z;

}
            //防止直接到边界
            maxx += 0.2;
            minx -= 0.2;
            maxy += 0.2;
            miny -= 0.2;
            maxz += 0.2;
            minz -= 0.2;

}

private void QChart_Load(object sender, EventArgs e)
        {

openGLControl1.OpenGLInitialized += OpenGLControl1_OpenGLInitialized;
            this.Resize += QChart_Resize;
            openGLControl1.MouseDown += on_MouseDown;
            openGLControl1.MouseLeave += on_MouseLeave;
            openGLControl1.MouseMove += on_MouseMove;
            openGLControl1.MouseUp += on_MouseUp;
            openGLControl1.MouseWheel += on_MouseWheel;
            SetupViewport();
        }

private void OpenGLControl1_OpenGLInitialized(object sender, EventArgs e)
        {
            SetupViewport();
        }

private void QChart_Resize(object sender, EventArgs e)
        {
            SetupViewport();
        }

//按键事件
        protected override void OnKeyDown(KeyEventArgs e)
        {
            base.OnKeyDown(e);
            if (e.KeyCode == Keys.Space)
            {
                this._x++;
                SetupViewport();
                this.Invalidate();
            }
        }

private void SetupViewport()
        {
            var w = this.Width;
            var h = this.Height;
            OpenGL GL = openGLControl1.OpenGL;
            GL.MatrixMode(OpenGL.GL_PROJECTION);
            GL.LoadIdentity();

GL.Viewport(0, 0, w, h); // Use all of the glControl painting area

if (h == 0) h = 1;
            GL.Perspective(60.0f, w / h, 0.01, 100);
            GL.LookAt(0, 0, zIndex, 0, 0, 0, 0, 1, 0);
        }

private bool msDown = false;//是否鼠标按下
        private int oldX = 0;//原始X坐标
        private int oldY = 0;
        private void on_MouseWheel(object sender, MouseEventArgs e)
        {

// MessageBox.Show(e.Delta+"");
            if (e.Delta > 0)
            {
                zIndex += 1;
                if (zIndex > 20) zIndex = 20;
            }
            else if (e.Delta < 0)
            {

zIndex -= 1;
                if (zIndex < 8) zIndex = 8;
            }

SetupViewport();
            this.Invalidate();
        }
        private void on_MouseDown(object sender, MouseEventArgs e)
        {
            msDown = true;
            oldX = e.X;//记录
            oldY = e.Y;
            Cursor = Cursors.Hand;
            ;
        }

private void on_MouseMove(object sender, MouseEventArgs e)
        {

if (points != null && points.Count > 0)
            {
                OpenGL gl = openGLControl1.OpenGL;
                double[] viewmatrix=new double[16];
                double[] projection = new double[16];
                int[] viewport = new int[4];

gl.GetDouble(OpenGL.GL_MODELVIEW_MATRIX, viewmatrix);
                gl.GetDouble(OpenGL.GL_PROJECTION,projection);
                gl.GetInteger(OpenGL.GL_VIEWPORT, viewport);

for (int i = 0; i < points.Count; i++)
                {
                    points[i].OnMouse = false;
                }
                
                int x = e.X;
                int y = e.Y;
                for (int i = 0; i < points.Count; i++)
                {

var sv = SharpGL.SceneGraph.OpenGLSceneGraphExtensions.Project(gl, new SharpGL.SceneGraph.Vertex((float)points[i].X, (float)points[i].Y, (float)points[i].Z));
                    if (Math.Abs(sv.X - x) < 3 && Math.Abs(sv.Y - y) < 3)
                    {
                        points[i].OnMouse = true;
                        break;
                    }
                }

}

if (!msDown) return;
            int dx = e.X - oldX;
            int dy = e.Y - oldY;

if (dy > 0) _rotationx += 0.5f;
            else if (dy < 0) _rotationx -= 0.5f;
            if (dx > 0) _rotationy += 0.5f;
            else if (dx < 0) _rotationy -= 0.5f;
            SetupViewport();
            this.Invalidate();

}

private void on_MouseUp(object sender, MouseEventArgs e)
        {
            msDown = false;
            Cursor = Cursors.Default;
        }

private void on_MouseLeave(object sender, EventArgs e)
        {
            msDown = false;
        }
    }

核心代码如下

C#,SharpGL开发的3D图表控件相关推荐

  1. 用于金融科技应用开发的高性能图表控件

    金钱使世界运转,因此,跟踪和控制金融交易和信息是当今互联世界中任何企业.金融机构或个人最重要的活动之一.为此,你需要金融技术应用. 根据不同的目的,金融技术应用可能有不同的功能,使其符合用户需要.例如 ...

  2. (转)基于MVC4+EasyUI的Web开发框架经验总结(4)--使用图表控件Highcharts

    http://www.cnblogs.com/wuhuacong/p/3736564.html 在我们做各种应用的时候,我们可能都会使用到图表统计,以前接触过一些不同的图表控件,在无意中发现了图表控件 ...

  3. C# winform使用scottplot图表控件快速入门设置XY轴缩放

    Hello大家好我是开箱测评小汪,在C#项目开发中使用图表控件,有时候我们希望放大或缩小图表控件来看数据细节和整体数据情况.所有本期课程将带介绍Scottplot图表控件如何来实现这个功能. 本期课程 ...

  4. android图表控件 坐标,android-charts 基于Java和Android开发的图形图表控件 | 李大仁博客...

    王晓龙 April 8th, 2014 at 09:44 | #1 我再github上看到了你写的控件,给了我很大启发,我现在在做K线图一类的图表,正好用到了您开发的这款控件,但是有些地方使用的不太舒 ...

  5. 提供多种2D和3D图表类型以及组合图、仪表的图表控件CHARTING

    .netCHARTING是一款功能强大的图表控件,利用.NET framework和GDI+为工作于ASP.NET和Winform的C#和VB.NET软件开发人 员提供可托管的图表解决方案,提供了多种 ...

  6. android开发原点表框架,Android图表控件MPAndroidChart——LineChart实现 XY轴、原点线的直尺刻度样式...

    接上文: Android图表控件MPAndroidChart--曲线图LineChart的使用(多条曲线) 其他相关文章: Android图表控件MPAndroidChart的简单介绍(MPAndro ...

  7. 微软图表控件MsChart

    转自:http://tech.ddvip.com/2008-11/122640479791375.html 昨天在网上看到了微软发布了.NET 3.5框架下的图表控件,第一时间抓下来看了一下,发觉功能 ...

  8. 基于.NET的图表控件解决方案

    2019独角兽企业重金招聘Python工程师标准>>> .netCHARTING是一个非常棒的.NET图表控件,对中文支持非常好,而且操作方便,开发快速,既有webform 也有wi ...

  9. ProEssentials实时三维图表控件

    原文来自方案网 http://www.fanganwang.com/Product-detail-item-1465.html,欢迎转载. 关键字:图表控件,工业图表,金融图表,工程图表 ProEss ...

  10. 三款ActiveX图表控件对比评测 TeeChart VS ProEssentials…

    概述:本文分别对几款优秀的ActiveX图表控件:TeeChart Pro ActiveX.ProEssentials.ChartDirector作了优势分析,对比评测,希望对用户的图表选型有所帮助. ...

最新文章

  1. 为啥不能用uuid做MySQL的主键!?
  2. 数据中心基础设施建设方案
  3. 二、入门爬虫,爬取百度图片
  4. 纵横免root框架打不开应用怎么办_很好用的软件多开神奇安卓欧皇十框架!!!...
  5. mysql 列换行 表设计 设计_今天来讲一下怎么利用MySql进行库表设计
  6. win10怎么设置默认输入法_win10系统输入法失效打不了字怎么办
  7. workerman相关
  8. Atom打开报错:Cannot load the system dictionary for zh-CN
  9. 使用 matlab 数字图像处理(九)—— 去卷积(deconvolution,逆滤波复原)
  10. 【面试】前端面试人事问题
  11. 以太网和wifi协议
  12. ppt保存为高分辨率图片(ppt2016)
  13. 【定量分析、量化金融与统计学】统计推断基础 番外(3)---假设检验例题讲解
  14. 《JOEL说软件》中文版翻译质量令人失望
  15. 攻防世界 WEB Web_python_flask_sql_injection
  16. 音频电解电容应用方法及经验
  17. BZOJ 2565 最长双回文串
  18. pink老师学习之Echarts
  19. TPS62240DDCR同步降压DC-DC转换器
  20. Python pathlib Path

热门文章

  1. Django 设置中文和中国时区
  2. 深入浅出Python机器学习2——基于Python语言的环境配置
  3. educoder软件工程导论结构化分析方法
  4. 程序员累了怎么办-兄弟连IT教育
  5. Matlab: 汉字转拼音函数包
  6. 中国城市经纬度表(精确到县区)Google地图用
  7. 微信开发之小程序获取手机号授权登录
  8. 适用于Chrome类浏览器的喜马拉雅音频下载插件
  9. 多商户商城系统功能拆解01讲-产品架构
  10. Java_接口练习题