回顧:上一篇文章介紹了winform繪製基本初等函數的類和工具,本次將一點點地介紹如何繪製函數圖像。
最後會貼出特別棒的圖像效果。
變量定義好了之後,我們就開始操作。
首先在窗體的加載事件中進行前期初始化。
private void Form1_Load(object sender, EventArgs e)
{
//獲得窗體中心點作為坐標系中心
beginPointX = (this.Width / 2);
beginPointY = (this.Height / 2);
//創建畫板
gra = this.CreateGraphics();
//初始化坐標系
zuobiaoxi();
}
初始化坐標系函數:
private void zuobiaoxi()
{
try
{
//從文本框中獲得坐標系精度參數
KEDU = Convert.ToInt32(textBox1.Text.Trim());
//從文本框中獲得曲線精度
LINEJD = Convert.ToDouble(textBox2.Text.Trim());
//從文本框中獲得曲線寬度
PointSize = Convert.ToInt32(textBox3.Text.Trim());
}
catch
{
}
Inittools();//畫板、畫筆工具初始化
//初始化X軸
InitX(new Point(0, beginPointY), new Point(this.Width, beginPointY));
//初始化Y軸
InitY(new Point(beginPointX, 0), new Point(beginPointX, this.Height));
}
畫板、畫筆初始化函數:
private void Inittools()
{
//用指定的顏色清除畫板上的內容
gra.Clear(Color.FromArgb(253,241,219));
//指定繪製模式 消除鋸齒
gra.SmoothingMode = SmoothingMode.AntiAlias;
//創建畫筆對象
pen = new Pen(Color.Green);
//指定畫筆的寬度
pen.Width = KEDU/20;
}
初始化X軸函數:
private void InitX(Point a,Point b)
{
gra.DrawLine(pen, a, b);
a.Y = beginPointY;
b.Y = beginPointY - KEDU/4;
for (int i = 0; i < (this.Width / 2)/this.KEDU; i++)
{
a.X = beginPointX - this.KEDU*i;
b.X = beginPointX - this.KEDU*i;
gra.DrawLine(pen, a, b);
a.X = beginPointX + this.KEDU * i;
b.X = beginPointX + this.KEDU * i;
gra.DrawLine(pen, a, b);
}
}
初始化Y軸函數:
private void InitY(Point a, Point b)
{
gra.DrawLine(pen, a, b);
a.X = beginPointX;
b.X = beginPointX + KEDU/4;
for (int i = 0; i < (this.Height / 2) / this.KEDU; i++)
{
a.Y = beginPointY - this.KEDU * i;
b.Y = beginPointY - this.KEDU * i;
gra.DrawLine(pen, a, b);
a.Y = beginPointY + this.KEDU * i;
b.Y = beginPointY + this.KEDU * i;
gra.DrawLine(pen, a, b);
}
}
這個時候,窗體加載完坐標系就搭建好了。界面如下圖所示。
接下來是繪製各個函數了。
繪製正弦函數:
private void button1_Click(object sender, EventArgs e)
{
if(flag == 1)
{
sign = 1;
new Thread(huizhi).Start();
}
}
所有的函數封裝代碼都放在「huizhi」函數中了。
繪製圖像的函數:
private void huizhi()
{
try
{
flag = 0;
zeroX = beginPointX;
zeroY = beginPointY;
Random r = new Random();
pen.Color = Color.FromArgb(r.Next(0,255), r.Next(0,255), r.Next(0,255));
realX = -Width;
while (realX < Width)
{
switch (sign)
{
//每一個case就是一種函數圖像
case 1:
realY = Math.Sin(realX / KEDU) * KEDU;
break;
case 2:
realY = Math.Asin(realX / KEDU) * KEDU;
break;
case 3:
realY = Math.Cos(realX / KEDU) * KEDU;
break;
case 4:
realY = Math.Acos(realX / KEDU) * KEDU;
break;
case 5:
realY = Math.Tan(realX / KEDU) * KEDU;
break;
case 6:
realY = Math.Atan(realX / KEDU) * KEDU;
break;
case 7:
realY = (Math.Cos(realX / KEDU) * KEDU) / (Math.Sin(realX / KEDU));
break;
case 8:
realY = (Math.PI / 2) * KEDU - (Math.Atan(realX / KEDU) * KEDU);
break;
case 9:
realY = (1 * KEDU) / (Math.Cos(realX / KEDU));
break;
case 10:
realY = (1 * KEDU) / (Math.Sin(realX / KEDU));
break;
case 11:
realY = realX * realX / KEDU;
break;
case 12:
realY = (realX * realX * realX) / (KEDU * KEDU);
break;
case 13:
realY = 1 * KEDU * KEDU / realX;
break;
case 14:
realY = Math.Log(realX / KEDU) * KEDU;
break;
case 15:
realY = realX;
break;
}
try
{
//畫指定矩形的內切圓 其實函數圖像就是由一個個小圓點組成的
gra.FillEllipse(pen.Brush, (float)(zeroX + realX - 1), (float)(zeroY - realY - 1), PointSize, PointSize);
}
catch
{
}
//按照刻度從左至右依次繪製
realX = realX + LINEJD;
}
flag = 1;
}
catch
{
}
}
好了,寫完了這些就大功告成了。其實最關鍵的部分就是每一個圖像的X點和Y點的位置,選定了X、Y的值,然後在那個位置畫個圓點就行了。
介紹一下參數:坐標軸精度就是每個刻度多長,就像放大縮小圖像一樣。曲線精度就是繪製出的線條的細緻程度,越小越好,但是小就繪製的慢。如果設置為0.01就特別慢,可以試試挺好玩的。曲線寬度就是繪製出的線條寬度。
前臺在繪製的時候會卡死,所以用了多線程,一次只能繪製一種圖像,但是可以覆蓋繪製。
還有就是畫的函數多了要點擊「初始化」按鈕清屏。
下面貼出一些效果,特別棒,而且根據不同的參數還有意想不到的圖像。
將坐標軸精度變得很小的時候,繪製正割、餘割函數會出現很漂亮的另外的曲線,它們上方的點陣又組成了另外的函數。
好了,今天就到這裡,想要源碼的同學可以關注私信我。我會第一時間回復。