//-----------------------------------------------------------------
//	波形を描画するクラス
//		複数の波形の描画に対応する
//
//		作成者：三上直樹，2023/01/30 作成，ⓒ三上直樹 2023
//-----------------------------------------------------------------

using System.Drawing;
using System.Drawing.Drawing2D;	// SmoothingMode, LineJoin で使用

using Mikami.Filter;

namespace Mikami
{
	public class WaveformDrawer
	{
		private readonly Font	myFont_;
		private readonly float	height_;
		private readonly int	ovs_;
		private readonly float	dpi_;
		private Color waveColor_;	// 波形の描画で使うデフォルトの色

		// コンストラクタ
		//		height	描画対象の PictureBox の高さ
		//		ovs		オーバーサンプリング比
		//		myColor	省略した場合は Color.Navy に設定される
		public WaveformDrawer(Font myFont, float height, int ovs, float dpiFactor,
								Color myColor = default)
		{
			myFont_ = myFont;
			height_ = height/2;
			dpi_ = dpiFactor;
			ovs_ = ovs;
			waveColor_ = (myColor == default) ? Color.Navy : myColor;
		}

		// 波形の描画
		//		波形の色を指定しない場合はコンストラクタで設定した色になる
		//		magV		縦方向の倍率を表す文字列
		//		magH		横方向の倍率を表す文字列
		//		penColor	Color.Empty または省略した場合は座標軸等を描画する
		public void Draw(Graphics gr, float[] xn, int nStart,
						 string mgaV, string magH, Color penColor = default)
		{
			float vert = float.Parse(mgaV);		// 縦方向の倍率
			float horizn = float.Parse(magH);	// 横方向の倍率
			float dt = dpi_*horizn;				// 横方向の倍率を反映
			float width = dpi_*100*ovs_;		// 描画する幅
			float hUnit = height_/1.5f;
			Color myColor = (penColor == default) ? waveColor_ : penColor;

			gr.TranslateTransform(36*dpi_, height_-12*dpi_);

			// 座標軸と目盛の描画
			if (penColor == default) DrawAxis(gr, hUnit, width, vert, horizn);

			// 波形表示の準備
			int t0 = ovs_*nStart + Interpolator.ORDER_/2;
			PointF[] pt = new PointF[(int)(width/dt)+1];	// 描画データの格納場所
			for (int n=0; n< pt.Length; n++)
				pt[n] = new PointF(n*dt, -vert*hUnit*xn[n+t0]);

			// クリッッピング領域の設定
			gr.SetClip(new RectangleF(0, -hUnit-5, width, 2*hUnit+10));

			Pen myPen = new Pen(myColor, 2) { LineJoin = LineJoin.Round };
			gr.SmoothingMode = SmoothingMode.AntiAlias;
			gr.DrawCurve(myPen, pt);	// 波形表示
			gr.SmoothingMode = SmoothingMode.Default;

			gr.ResetTransform();
		}

		// 座標軸と目盛の描画
		private void DrawAxis(Graphics gr, float hUnit, float Width,
							  float vert, float horizn)
		{
			Brush myBrush = Brushes.Black;
			float y1 = height_ - 22*dpi_;

			// 横軸の目盛の表示
			for (int n=0; n<=10; n++)
				gr.DrawLine(Pens.Silver, n*Width/10, hUnit, n*Width/10, -hUnit);

			gr.DrawString("0", myFont_, myBrush, -4*dpi_, y1);
			string tMax = (10.0f/horizn).ToString();
			// 時間軸の最大値
			gr.DrawString(tMax, myFont_, myBrush, Width-(3+2*tMax.Length)*dpi_, y1);

			gr.DrawString("時間 [ms]", myFont_, myBrush, Width/2-32*dpi_, y1+14*dpi_);

			// 縦軸の目盛の表示
			for (int n=0; n<5; n++)
				gr.DrawLine(Pens.Silver, 0, (n-2)*hUnit/2, Width, (n-2)*hUnit/2);

			string str = (1.0f/vert).ToString();	// 縦倍率
			gr.DrawString(str, myFont_, myBrush,
						  -(7+5.8f*str.Length)*dpi_, -hUnit-9*dpi_);
			gr.DrawString("-"+str, myFont_, myBrush,
						  -(11+5.8f*str.Length)*dpi_, hUnit-9*dpi_);
		}
	}
}
