使用者透過介面上的控制項設定繪圖參數,點擊繪圖按鈕後,程式依據 PictureBox 尺寸建立 Bitmap 物件,並作為參數傳遞給核心繪圖函數 `Draw(Bitmap myImage)`。
private void Draw(Bitmap myImage)
{
try
{
Graphics g = Graphics.FromImage(myImage);
SyntaxAnalyse.DicVariable.Clear();
// 確定計算範圍
int intMin = this.numMin.Value < this.numMax.Value ? (int)this.numMin.Value : (int)this.numMax.Value;
int intMax = this.numMin.Value < this.numMax.Value ? (int)this.numMax.Value : (int)this.numMin.Value;
// 初始化變量 n
TokenRecord TokenN = m_Analyse.Analyse("n");
TokenN.TokenValueType = typeof(double);
TokenN.TokenValue = intMin;
// 初始化各繪圖資訊
foreach (DrawInfo item in this.m_DrawInfoList)
{
item.InitialToken(m_Analyse);
}
// 設定高品質繪圖模式
g.SmoothingMode = System.Drawing.Drawing2D.SmoothingMode.HighQuality;
// 繪製座標軸
g.DrawLine(Pens.Black, 0, this.picImage.Height / 2, this.picImage.Width, this.picImage.Height / 2); // X軸
g.DrawLine(Pens.Black, this.picImage.Width / 2, 0, this.picImage.Width / 2, this.picImage.Height); // Y軸
// 平移座標系至圖片中心
g.TranslateTransform(Convert.ToSingle(myImage.Width / 2), Convert.ToSingle(myImage.Height / 2));
// 計算表達式生成點集
for (int intIndex = intMin; intIndex <= intMax; intIndex++)
{
TokenN.TokenValue = (double)intIndex;
foreach (DrawInfo item in this.m_DrawInfoList)
{
item.Execute();
}
}
// 繪製所有波形
foreach (DrawInfo item in this.m_DrawInfoList)
{
g.DrawLines(new Pen(item.LineColor, item.LineWidth), item.PointList.ToArray());
}
// 修正 Y 軸方向(GDI+ 原點在左上角)
myImage.RotateFlip(RotateFlipType.Rotate180FlipX);
// 繪製刻度與標籤
SolidBrush myBrush = new SolidBrush(Color.Black);
for (int intX = 0; intX < myImage.Width / 2; intX += (int)(this.numScale.Value))
{
g.DrawLine(Pens.Black, intX, 0, intX, -3);
g.DrawString(intX.ToString(), this.Font, myBrush, intX + 1, 1);
if (intX == 0) continue;
g.DrawLine(Pens.Black, -intX, 0, -intX, -3);
g.DrawString("-" + intX.ToString(), this.Font, myBrush, -intX + 1, 1);
}
for (int intY = 0; intY < myImage.Height / 2; intY += (int)this.numScale.Value)
{
g.DrawLine(Pens.Black, 0, -intY, 3, -intY);
g.DrawString(intY.ToString(), this.Font, myBrush, 1, -intY + 1);
if (intY == 0) continue;
g.DrawLine(Pens.Black, 0, intY, 3, intY);
g.DrawString("-" + intY.ToString(), this.Font, myBrush, 1, intY + 1);
}
// 繪製圖例
g.TranslateTransform(Convert.ToSingle(myImage.Width / 2 * -1), Convert.ToSingle(myImage.Height / 2 * -1));
int intOffsetX = 10, intOffsetY = 10;
int intLegendHeight = (int)g.MeasureString("123", this.Font).Height;
foreach (DrawInfo item in m_DrawInfoList)
{
using (SolidBrush LegendBrush = new SolidBrush(item.LineColor))
{
g.FillRectangle(LegendBrush, intOffsetX, intOffsetY, 30, intLegendHeight);
g.DrawString(item.Name, this.Font, LegendBrush, intOffsetX + 30 + 5, intOffsetY);
intOffsetY += intLegendHeight + 5;
}
}
}
catch (Exception ex)
{
MessageBox.Show("錯誤信息為:" + ex.Message, "運算發生錯誤", MessageBoxButtons.OK, MessageBoxIcon.Information);
}
}