信号プロット関係 - peace098beat/windows_applicaciton GitHub Wiki

WaveFormChart

using Backend;
using System;
using System.Drawing;
using System.Drawing.Drawing2D;
using System.Windows.Forms;

namespace Frontend
{
    class WaveFormChart : Panel
    {

        /*************************************************************************/
        /* 設定定数
        /*************************************************************************/
        public static int NDATA = 500; //ろうそく足の本数

        public static Padding mrgn = new Padding(10, 10, 50, 30); // [サイズ]  Chart1のグラフマージン
        protected static int horzMrgn = mrgn.Left + mrgn.Right; // マージン
        protected static int vertMrgn = mrgn.Top + mrgn.Bottom;

        protected static Font font = new Font("Arial", 7); // フォント1
        protected static Font font2 = new Font("Arial", 7); // フォント2

        protected static Pen penRed = new Pen(Color.Red, 2);
        protected static Pen penBlue = new Pen(Color.Blue, 2);
        protected static Pen penGrayDot = new Pen(Color.Gray, 1) { DashStyle = DashStyle.Dot }; // 罫線点線

        /*************************************************************************/
        /* コントロール系変数
        /*************************************************************************/
        /* メンバ */
        protected int nBgn; // 表示する先頭レコード番号 [0, data.Length-NDATA]

        /* オプション */
        protected static TextFormatFlags mid = TextFormatFlags.HorizontalCenter | TextFormatFlags.VerticalCenter; // センター寄オプション
        protected static TextFormatFlags left = TextFormatFlags.Left | TextFormatFlags.VerticalCenter; // センター寄オプション
        protected double[] Tick = {1e-8, 5e-8, 1e-7, 5e-7, 1e-6, 5e-6, 1e-5, 5e-5,
                         1e-4, 5e-4, 1e-3, 5e-3, 1e-2, 5e-2, 1e-1, 5e-1, 1, 2, 5, 10, 20, 50, 100, 200, 500,1000, 10000, 20000, 50000 };

        protected Rectangle MainChartRect; // Chart1とChart2をあわせたRectangle

        /* グラフのレンジ */
        protected double xMin = double.MaxValue;
        protected double xMax = double.MinValue;
        protected double yMin = double.MaxValue;
        protected double yMax = double.MinValue;
        protected double xTickValue = 0; // 一目盛りの大きさ
        protected double yTickValue = 0; // 一目盛りの大きさ

        public string XLabel { set; get; }
        public string YLabel { set; get; }
        public string Title { set; get; }

        protected bool IsMouseDraging = false;

        /*************************************************************************
        * 座標変換
        *************************************************************************/

        /// <summary> グラフ座標からウィンドウ座標へ変換 </summary>
        /// <param name="x">グラフ座標上の正規化された位置(0~1)</param>
        /// <returns>パネル内のピクセル値</returns>
        int nx(double x)
        {
            return (int)(MainChartRect.Left + x * MainChartRect.Width);
        }

        /// <summary>グラフ座標からウィンドウ座標へ変換</summary>
        /// <param name="y">グラフ座標上の正規化された位置(0~1)</param>
        /// <returns>パネル内のピクセル値</returns>
        int ny(double y)
        {
            return (int)(MainChartRect.Top + (1.0 - y) * MainChartRect.Height);
        }

        double normX(double x)
        {
            return (x - xMin) / (xMax - xMin);
        }
        double normY(double y)
        {
            return (y - yMin) / (yMax - yMin);
        }



        /*************************************************************************
         * コンストラクタ
         *************************************************************************/

        /// <summary>
        /// コンストラクタ
        /// </summary>
        public WaveFormChart()
        {
            this.SetStyle(ControlStyles.ResizeRedraw, true);
            this.DoubleBuffered = true; // ダブルバッファリング: ちらつき防止
            this.Size = new Size(600, 400);

            // マウスイベント
            this.MouseMove += new MouseEventHandler(mouseMove);
            this.MouseDown += new MouseEventHandler(mouseDown);
            this.MouseUp += new MouseEventHandler(mouseUp);
            this.MouseWheel += new MouseEventHandler(mouserWheel);
        }


        /*************************************************************************
        * プロットデータ
        *************************************************************************/
        /// <summary>
        /// プロットする打音
        /// </summary>
        protected DaonPlotData TargetDaon = null;

        /// <summary>
        /// プロット用の打音データ
        /// </summary>
        public class DaonPlotData
        {
            public Daon Daon { set; get; }
            public float[] X { set; get; }
            public float[] Y { set; get; }
        }

        /// <summary>
        /// チャートデータのセット
        /// </summary>
        public void AddXY(float[] x, float[] y, Daon daon)
        {

            TargetDaon = new DaonPlotData() { Daon = daon, X = x, Y = y };
            this.Refresh();
        }

        /// <summary>
        /// データのクリア
        /// </summary>
        public void Clear()
        {
            TargetDaon = null;
            this.Refresh();
        }


        /*************************************************************************
        * マウスイベント
        *************************************************************************/
        private void mouseMove(object sender, MouseEventArgs e)
        {
        }
        private void mouseDown(object sender, MouseEventArgs e)
        {
        }
        private void mouseUp(object sender, MouseEventArgs e)
        {
        }
        private void mouserWheel(object sender, MouseEventArgs e)
        {
        }

        /*************************************************************************
         * シーケンス関数
         *************************************************************************/
        void CalcXYRange()
        {
            /* 最大最小の計算 */
            xMax = double.MinValue;
            xMin = double.MaxValue;
            yMax = double.MinValue;
            yMin = double.MaxValue;

            for (int n = 0; n < TargetDaon.X.Length; n++)
            {
                xMax = Math.Max(xMax, TargetDaon.X[n]);
                xMin = Math.Min(xMin, TargetDaon.X[n]);
                yMax = Math.Max(yMax, TargetDaon.Y[n]);
                yMin = Math.Min(yMin, TargetDaon.Y[n]);
            }

            // スケール
            double xRange = xMax - xMin;
            double yRange = yMax - yMin;

            //xMax = xMax + xRange * 0.1;
            //xMin = xMin - xRange * 0.1;
            //yMax = yMax + yRange * 0.1;
            //yMin = yMin - yRange * 0.1;
            yMax = 1.1;
            yMin = -1.1;

            // X最大・最小を計算
            for (int i = 0; i < Tick.Length; i++)
            {
                // 7本分ぐらいのTick(幅)を選択
                if (7 * Tick[i] < (xMax - xMin))
                    xTickValue = Tick[i];
                else
                    continue;
            }
            // Tick単位の大きさに変更
            xMax = Math.Ceiling(xMax / xTickValue) * xTickValue; // 大きい側を使用
            xMin = Math.Floor(xMin / xTickValue) * xTickValue; // 小さい側を使用

            // Y最大・最小を計算
            for (int i = 0; i < Tick.Length; i++)
            {
                // 7本分ぐらいのTick(幅)を選択
                if (4 * Tick[i] < (yMax - yMin))
                    yTickValue = Tick[i];
                else
                    continue;
            }
            // Tick単位の大きさに変更
            yMax = Math.Ceiling(yMax / yTickValue) * yTickValue; // 大きい側を使用
            yMin = Math.Floor(yMin / yTickValue) * yTickValue; // 小さい側を使用

        }
        void drawXLine(Graphics g)
        {
            // X軸の目盛りの数
            int numTicks = (int)((xMax - xMin) / xTickValue);

            for (int n = 0; n < numTicks; n++)
            {
                double _x = (double)n / (numTicks - 1); // 正規化

                // X軸の罫線の描画
                if (n > 0 && n < numTicks - 1)
                {
                    g.DrawLine(penGrayDot, nx(_x), ny(0), nx(_x), ny(1));
                }

                // X軸の目盛り文字
                Rectangle RC_DateText = new Rectangle(nx(_x) - 15 - (n == (numTicks - 1) ? 5 : 0), ny(0), 30, 20);
                string dateString = $"{n * xTickValue + xMin}";
                TextRenderer.DrawText(g, dateString, font, RC_DateText, Color.Black, mid);
            }
        }
        /// <summary>
        /// Y罫線のびょうが 
        /// </summary>
        void drawYLine(Graphics g)
        {
            // Y軸の目盛りの数
            int numTicks = (int)((yMax - yMin) / yTickValue);

            for (int n = 0; n < numTicks; n++)
            {
                double _y = (double)n / (numTicks - 1); // 正規化

                //Y軸の罫線の描画
                if (0 < n && n < numTicks)
                {
                    g.DrawLine(penGrayDot, nx(0), ny(_y), nx(1), ny(_y));
                }
                // Y軸の目盛り文字
                var RectTitle = new Rectangle(nx(1), ny(_y) - (n > 0 ? 10 : 14), 50, 20);
                string num = (yMin + n * yTickValue).ToString();
                TextRenderer.DrawText(g, num, font, RectTitle, Color.Black, left);
            }
        }



        /*************************************************************************
         * 再描画メソッド
         *************************************************************************/
        protected override void OnPaint(PaintEventArgs e)
        {

            base.OnPaint(e);
            Graphics g = e.Graphics;


            // グラフ(2つあわせた)サイズ ※リサイズのたびに作り直される
            MainChartRect = new Rectangle(mrgn.Left, mrgn.Top, ClientSize.Width - horzMrgn, ClientSize.Height - vertMrgn);

            /* チャートの外枠を表示 */
            Rectangle RCChart1 = new Rectangle(nx(0), ny(1), nx(1) - nx(0), ny(0) - ny(1));
            g.FillRectangle(Brushes.White, RCChart1);
            g.DrawRectangle(Pens.Black, RCChart1);

            /* チャートの外枠を表示 */
            int margin = 3;
            Rectangle RCChartOuter = new Rectangle(0 + margin, 0 + margin, ClientSize.Width - 2 * margin, ClientSize.Height - 2 * margin);
            g.DrawRectangle(Pens.Black, RCChartOuter);


            // もしデータが無い場合は処理無し
            if (TargetDaon == null) return;

            /* 最大最小の再計算 */
            this.CalcXYRange();


            /***********************/
            /* x軸罫線,目盛り描画 */
            /***********************/
            this.drawXLine(g);

            /***********************/
            /* Y軸罫線,目盛りの描画 */
            /***********************/
            this.drawYLine(g);

            /***********************/
            /* 信号をプロット */
            /***********************/

            int Nx = TargetDaon.X.Length;
            int Ny = TargetDaon.Y.Length;

            if (Nx != Ny)
                throw new ArgumentOutOfRangeException();

            for (int i = 1; i < Ny; i++)
            {
                int x1 = nx(normX(TargetDaon.X[i - 1]));
                int y1 = ny(normY(TargetDaon.Y[i - 1]));
                int x2 = nx(normX(TargetDaon.X[i]));
                int y2 = ny(normY(TargetDaon.Y[i]));

                g.DrawLine(Pens.Blue, new Point(x1, y1), new Point(x2, y2));
            }




        }



    }
}
⚠️ **GitHub.com Fallback** ⚠️