
第
8
章
三维图形
【本章导读】
第
7
章中,我们详细地讨论了创建三维图形的基础知识,包括三维矩阵,变换和坐标
体系等。本章我们将应用这些知识来创建各种三维图形,例如三维折线图,三维网格和曲
面图,轮廓图,三维柱状图,四维切片图和三维复合图。
本章的
C#
应用程序示例基本上可以满足于读者三维应用程序的基础要求。基于这些
示例,读者略作修改或甚至不作修改,即可很容易地创建你自己的应用于实际工作的三维
图形应用程序,此外本章的所有应用程序均是基于双缓存实现的并且几乎所有的类均实现
了序列化和反序列化。本章主要介绍:
三维图形的基本元素;
通用三维图形函数包的实现;
各种三维图形的算法及实现。
8.1
三维图形基础
我们应用于三维图表的坐标体系是基于正交的坐标体系(直角坐标体系),这是三维
制图的标准方法,该方法意味着不能将透视投影变换应用于三维图表程序。仰角和方位角
变换用于在二维计算机屏幕上操纵三维图形的视图。我们通过讨论三维图表的三个基本
类:
Point3
、
Matrix3
和
ChartStyle
来开始本章的内容。
8.1.1 Point3 和 Matrix3 类
Point3
类,该类是一个通用类可以用于任何三维图形应用程序。在此修改该类以便纳
入一些三维图形的特殊功能:
using System;
using System.Collections.Generic;
using System.Text;
namespace Example8_1_1
{

C#二维三维 图形绘制工程实例宝典
474
/// <summary>
///
处理点的坐标的转换由世界坐标体系转换到设备坐标体系
/// </summary>
public class Point3
{
#region Vatiables
public float X;
public float Y;
public float Z;
public float W = 1f;
#endregion
#region Constructors
public Point3()
{
}
public Point3(float x, float y, float z, float w)
{
X = x;
Y = y;
Z = z;
W = w;
}
#endregion
#region Methods
public void Transform(Matrix3 m)
{
float[] result = m.VectorMultiply(new float[4] { X, Y, Z, W
});
X = result[0];
Y = result[1];
Z = result[2];
W = result[3];
}
public void Transform(Matrix3 m, Form1 form1, ChartStyle cs)
{
//
初始化点
float x1 = (X - cs.XMin) / (cs.XMax-cs.XMin) - 0.5f;
float y1 = (Y - cs.YMin) / (cs.YMax - cs.YMin) - 0.5f;
float z1 = (Z - cs.ZMin) / (cs.ZMax - cs.ZMin) - 0.5f;
//
用矩阵
m
完成点的转换
float[] result = m.VectorMultiply(new float[4] { x1, y1,
z1, W });
X = result[0];
Y = result[1];
//
世界坐标体系转换到设备坐标体系
float xShift = 1.05f;
float xScale = 1;

第 8 章 三维图形
475
float yShift = 1;
float yScale = 1;
if (cs.Title != " " || cs.Title != "")
{
yShift = 1.05f;
yScale = 0.9f;
}
if (cs.IsColorBar)
{
xShift = 0.95f;
xScale = 0.9f;
}
X = (xShift + xScale * X) * form1.PlotPanel.Width / 2;
Y = (yShift - yScale * Y) * form1.PlotPanel.Height / 2;
}
#endregion
}
}
在该类中,增加了
TransForm
方法的重载
public void Transform(Matrix3 m, Form1 form1, ChartStyle cs)
{
……
}
它具有三个参数:变换矩阵
(Matrix3)
,类
Form1
的实例
(form1)
用于显示图形及
ChartStyle
类的对象实例
(cs)
。在该方法中,首先在一个单位立方体的数据范围内归一化
x
、
y
和
z
元素,以便该单位立方体内的点的转换独立于实际的数据范围,然后利用转换矩阵
对归一化后的点进行转换,最后,对点的坐标体系进行从世界坐标体系到设备坐标体系的
转换。细心的读者可能注意到,在该重载方法中,只有点的
x
和
y
元素进行转换,而
z
和
w
元素则保留点的原始值,代码段如下:
float[] result = m.VectorMultiply(new float[4] { x1, y1, z1, W });
X = result[0];
Y = result[1];
浮点型数据
result
存储了变换后的坐标信息,
x
和
y
坐标以
result
数组中获得变换后的
坐标值。而
z
和
w
元素未从
result
数组中获取新的值,而是保留了它们的原始信息,不然
的话,正交变换后,
z
元素将是原始的
x
、
y
和
z
元素的组合,从而丢失原始的
z
坐标信息,
但是在三维图形中,我们需要利用原始的
z
坐标信息以便完成三维图形的颜色影射。因此
修改了
Transform
方法,并将其应用于点的变换,从而保留原始的
z
元素信息。
同时,在
Matrix3
类中,添加了
AzimuthElevation
方法的重载:
public static Matrix3 AzimuthElevation(float elevation, float azimuth)
{
Matrix3 result = new Matrix3();
//
确保视角范围在
[-90, 90]
if (elevation > 90)
elevation = 90;

C#二维三维 图形绘制工程实例宝典
476
else if (elevation < -90)
elevation = -90;
//
确保方位角范围在
[-180, 180]
if (azimuth > 180)
azimuth = 180;
else if (azimuth < -180)
azimuth = -180;
elevation = elevation * (float)Math.PI / 180.0f;
float sne = (float)Math.Sin(elevation);
float cne = (float)Math.Cos(elevation);
azimuth = azimuth * (float)Math.PI / 180.0f;
float sna = (float)Math.Sin(azimuth);
float cna = (float)Math.Cos(azimuth);
result.M[0, 0] = cna;
result.M[0, 1] = sna;
result.M[0, 2] = 0;
result.M[1, 0] = -sne * sna;
result.M[1, 1] = sne * cna;
result.M[1, 2] = cne;
result.M[2, 0] = cne * sna;
result.M[2, 1] = -cne * cna;
result.M[2, 2] = sne;
return result;
}
8.1.2 ChartStyle 类
ChartStyle
类如下的代码段显示了该类的成员变量及相对应的属性:
using System;
using System.Drawing;
using System.Drawing.Drawing2D;
using System.Text;
using System.Windows.Forms;
using System.Runtime.Serialization;
namespace Example8_1_1
{
/// <summary>
///
处理图形区域的各种属性
/// </summary>
///
[Serializable]
public class ChartStyle : ICloneable, ISerializable
{
#region Variables
private Form1 form1;
private float _mxMax = 5f;
private float _mxMin = -5f;
private float _myMax = 3f;

第 8 章 三维图形
477
private float _myMin = -3f;
private float _mzMax = 6f;
private float _mzMin = -6f;
private float _mxTick = 1f;
private float _myTick = 1f;
private float _mzTick = 3f;
private Font _mtickFont = new Font("Arial Narrow",8,
FontStyle.Regular);
private Color _mtickColor = Color.Black;
private string _mtitle = "My 3D Chart";
private Font _mtitleFont = new Font("Arial Narrow", 14,
FontStyle.Regular);
private Color _mtitleColor = Color.Black;
private string _mxLabel = "X Axis";
private string _myLabel = "Y Axis";
private string _mzLabel = "Z Axis";
private Font _mlabelFont = new Font("Arial Narrow", 10,
FontStyle.Regular);
private Color _mlabelColor = Color.Black;
private float _melevation = 30;
private float _mazimuth = -37.5f;
private bool _misXGrid = true;
private bool _misYGrid = true;
private bool _misZGrid = true;
LineStyle _mgridStyle;
LineStyle _maxisStyle;
private bool _misColorBar = false;
#endregion
#region Constructors
public ChartStyle(Form1 fm1)
{
form1 = fm1;
_mgridStyle = new LineStyle();
_maxisStyle = new LineStyle();
}
/// <summary>
///
拷贝构造函数
/// </summary>
public ChartStyle(ChartStyle rhs)
{
_mxMax = rhs._mxMax;
_mxMin = rhs._mxMin;
_myMax = rhs._myMax;
_myMin = rhs._myMin;
_mzMax = rhs._mzMax;
_mzMin = rhs._mzMin;
_mxTick = rhs._mxTick;
_myTick = rhs._myTick;
_mzTick = rhs._mzTick;
_mtickFont = rhs._mtickFont;
_mtickColor = rhs._mtickColor;
- 1
- 2
- 3
- 4
- 5
前往页