首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> C語言 >> 關於C語言

C# 計算器實作系列:函數波形繪製(4)——核心繪圖邏輯與 GDI+ 實作詳解

     編輯:關於C語言

介面控制與繪圖初始化

使用者透過介面上的控制項設定繪圖參數,點擊繪圖按鈕後,程式依據 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);
    }
}

關鍵技術點總結

  • 語法樹複用:僅更新變量 Token 值,重複呼叫 Execute() 避免重複解析
  • 座標系轉換:TranslateTransform 將原點移至中心,RotateFlip 修正 Y 軸方向
  • 高品質渲染:SmoothingMode.HighQuality 確保曲線平滑
  • 動態刻度:根據使用者設定的間距自動繪製座標軸刻度與數值標籤
  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved