ecgdraw.cs

来自「ecg tool kit for medical image retrieval」· CS 代码 · 共 1,206 行 · 第 1/4 页

CS
1,206
字号
				else
				{
					_X = x * (DpiX * Inch_Per_mm) * _mm_Per_GridLine;
					_Y = y * (DpiY * Inch_Per_mm) * _mm_Per_GridLine;
				}

				_LeadType = LeadType.Unknown;
				_AVM = 1000.0f;
				_SamplesPerSecond = sps;
				_Start = 0;
				_End = length;
				_Data = null;
				_fmm_Per_mV = fmm_Per_mV;
			}
			/// <summary>
			/// Constructor to draw provided sample data.
			/// (one sample is one pixel on the X-axis)
			/// </summary>
			/// <param name="bInPixels">x and y are in pixels if this value is true</param>
			/// <param name="fmm_Per_mV">millimeters per milliVolt</param>
			/// <param name="x">position X in pixels or millimeters</param>
			/// <param name="y">position Y in pixels or millimeters</param>
			/// <param name="leadType">type of the lead</param>
			/// <param name="avm">AVM of signal data</param>
			/// <param name="sps">samples per seconds of signal data</param>
			/// <param name="start">start point in signal data</param>
			/// <param name="end">end point in signal data</param>
			/// <param name="data">signal data</param>
			public ECGDrawSection(bool bInPixels, float fmm_Per_mV, float x, float y, LeadType lt, double avm, int sps, int start, int end, short[] data)
			{
				if (bInPixels)
				{
					_X = x;
					_Y = y;
				}
				else
				{
					_X = x * (DpiX * Inch_Per_mm) * _mm_Per_GridLine;
					_Y = y * (DpiY * Inch_Per_mm) * _mm_Per_GridLine;
				}

				_LeadType = lt;
				_AVM = avm;
				_SamplesPerSecond = sps;
				_Start = start;
				_End = end;
				_Data = data;
				_fmm_Per_mV = fmm_Per_mV;
			}

			private float _X;
			private float _Y;
			private LeadType _LeadType;
			private double _AVM; // AVM in uV
			private int _SamplesPerSecond;
			private int _Start;
			private int _End;
			private short[] _Data;
			private float _fmm_Per_mV;
			private Color _SignalColor = ECGDraw.SignalColor;

			/// <summary>
			/// set color that will be used to draw signal.
			/// </summary>
			public Color SignalColor
			{
				set
				{
					_SignalColor = value;
				}
			}

			public int DrawSignal(Graphics g)
			{
				float fPixel_Per_uV = _fmm_Per_mV * DpiY * Inch_Per_mm * 0.001f;

				Pen myPen = new Pen(_SignalColor);

				int length = _End - _Start + 1;

				if (_Data == null)
				{
					int end = (_SamplesPerSecond * _End) / 5;

					if (_End == 1)
					{
						g.DrawLine(myPen, _X, _Y, _X, _Y - (float) (_AVM * fPixel_Per_uV));
						g.DrawLine(myPen, _X, _Y - (float) (_AVM * fPixel_Per_uV), _X + end, _Y - (float) (_AVM * fPixel_Per_uV));
						g.DrawLine(myPen, _X + end, _Y - (float) (_AVM * fPixel_Per_uV), _X + end, _Y);
					}
					else
					{
						int a = ((end * 2) / 10),
							b = ((end * 7) / 10);

						g.DrawLine(myPen, _X, _Y, _X + a, _Y);
						g.DrawLine(myPen, _X + a, _Y, _X + a, _Y - (float) (_AVM * fPixel_Per_uV));
						g.DrawLine(myPen, _X + a, _Y - (float) (_AVM * fPixel_Per_uV), _X + b, _Y - (float) (_AVM * fPixel_Per_uV));
						g.DrawLine(myPen, _X + b, _Y - (float) (_AVM * fPixel_Per_uV), _X + b, _Y);
						g.DrawLine(myPen, _X + b, _Y, _X + end, _Y);
					}
				}
				else
				{
					if (_LeadType != ECGConversion.ECGSignals.LeadType.Unknown)
					{
						Font fontText = new Font("Verdana", _TextSize);
						SolidBrush solidBrush = new SolidBrush(TextColor);

						g.DrawString(
							_LeadType.ToString(),
							fontText,
							solidBrush,
							_X + 4.0f,
							_Y - (1250.0f * fPixel_Per_uV));

						solidBrush.Dispose();
						fontText.Dispose();
					}

					g.DrawLine(myPen, _X, _Y - (1000.0f * fPixel_Per_uV), _X, _Y - (1250.0f * fPixel_Per_uV));

					int t2=1;
					for (;t2 < length;t2++)
					{
						int t1 = t2 - 1;

						short
							y1 = short.MinValue,
							y2 = short.MinValue;

						if ((t1 >= 0)
						&&	(t2 <= (_End - _Start))
						&&	((t1 + _Start) >= 0)
						&&	((t2 + _Start) < _Data.Length))
						{
							y1 = _Data[t1 + _Start];
							y2 = _Data[t2 + _Start];
						}

						if ((y1 != short.MinValue)
						&&	(y2 != short.MinValue))
						{
							g.DrawLine(
								myPen,
								_X + t1,
								_Y - (float) (y1 * _AVM * fPixel_Per_uV),
								_X + t2,
								_Y - (float) (y2 * _AVM * fPixel_Per_uV));
						}
					}

					t2--;

					g.DrawLine(myPen, _X + t2, _Y - (1000.0f * fPixel_Per_uV), _X + t2, _Y - (1250.0f * fPixel_Per_uV));
				}

				myPen.Dispose();

				return _End;
			}
		}
		/// <summary>
		/// Function to draw an ECG using a certain draw type.
		/// </summary>
		/// <param name="myGraphics">graphics object to draw with.</param>
		/// <param name="signals">signal data.</param>
		/// <param name="dt">Draw type of ECG.</param>
		/// <param name="nTime">Start drawing at this sample number.</param>
		/// <param name="fmm_Per_s">mm per second</param>
		/// <param name="fmm_Per_mV">mm per mV</param>
		/// <param name="bAllowResample">True if resample of signal is allowed.</param>
		/// <returns>Sample number to start next draw ECG on.</returns>
		public static int DrawECG(Graphics myGraphics, ECGSignals.Signals signals, ECGDrawType dt, int nTime, float fmm_Per_s, float fmm_Per_mV, bool bAllowResample)
		{
			if (myGraphics == null)
				return -1;

			if (signals == null)
				return -2;

			if ((PossibleDrawTypes(signals) & dt) == 0)
				return -3;

			int ret = 0;

			float
				fPixel_Per_ms = fmm_Per_s * DpiX * Inch_Per_mm * 0.001f,
				fPixel_Per_s = fmm_Per_s * DpiX * Inch_Per_mm, 
				fPixel_Per_uV = fmm_Per_mV * DpiY * Inch_Per_mm * 0.001f,
				fLeadYSpace = _uV_Per_Channel * fPixel_Per_uV,
				fGridX = (DpiX * Inch_Per_mm) * _mm_Per_GridLine,
				fGridY = (DpiY * Inch_Per_mm) * _mm_Per_GridLine;

			int nMinX = 0,
				nMinY = 0,
				nMaxX = 52,
				nMaxY = 32;

			ECGDrawSection[] drawSections = null;

			int nOldSamplesPerSecond = 0;

			// begin: resample signals to fit. (using a dirty solution)
			if (((dt != ECGDrawType.Median)
			&&	 (signals.RhythmSamplesPerSecond != (int) fPixel_Per_s))
			||	((dt == ECGDrawType.Median)
			&&	 (signals.MedianSamplesPerSecond != (int) fPixel_Per_s)))
			{
				if (!bAllowResample)
				{
					nOldSamplesPerSecond = (dt == ECGDrawType.Median) ? signals.MedianSamplesPerSecond : signals.RhythmSamplesPerSecond;
					signals = signals.Clone();
				}

				// You should note that if signal is already resampled, but dpi changes the new signal
				// will be resampled based on already resampled information instead of reloading from
				// orignal.
				int RI = ECGConversion.ECGTool.ResampleInterval;
				ECGConversion.ECGTool.ResampleInterval /= DirtSolutionFactor;
				for (int i=0;i < signals.NrLeads;i++)
				{
					ECGTool.ResampleLead(signals[i].Rhythm, (int) signals.RhythmSamplesPerSecond * DirtSolutionFactor, (int) (fPixel_Per_s * DirtSolutionFactor), out signals[i].Rhythm);

					if ((signals.MedianSamplesPerSecond != 0)
					&&	(signals[i].Median != null))
						ECGTool.ResampleLead(signals[i].Median, (int) signals.MedianSamplesPerSecond * DirtSolutionFactor, (int) (fPixel_Per_s * DirtSolutionFactor), out signals[i].Median);

					signals[i].RhythmStart = (signals[i].RhythmStart * (int) (fPixel_Per_s * DirtSolutionFactor)) / (int) (signals.RhythmSamplesPerSecond * DirtSolutionFactor);
					signals[i].RhythmEnd = (signals[i].RhythmEnd * (int) (fPixel_Per_s * DirtSolutionFactor)) / (int) (signals.RhythmSamplesPerSecond * DirtSolutionFactor);
				}
				ECGConversion.ECGTool.ResampleInterval = RI;

				nTime = (nTime * (int) (fPixel_Per_s * DirtSolutionFactor)) / (int) (signals.RhythmSamplesPerSecond * DirtSolutionFactor);

				// set new rhythm per samples.
				signals.RhythmSamplesPerSecond = (int) fPixel_Per_s;
				if (signals.MedianSamplesPerSecond != 0)
					signals.MedianSamplesPerSecond = (int) fPixel_Per_s;
			}

			switch (dt)
			{
				case ECGDrawType.Regular:
				{
					nMinY = (int) (_TextSize * DpiY * Inch_Per_mm * .4f);

					// begin: drawing of ECG.
					if (Math.Ceiling(fLeadYSpace * signals.NrLeads) >= (myGraphics.VisibleClipBounds.Height - nMinY))
					{
						fLeadYSpace = (float) Math.Floor(((myGraphics.VisibleClipBounds.Height - nMinY - fGridY) / signals.NrLeads) / fGridY) * fGridY;
					}

					DrawGrid(myGraphics, fLeadYSpace, signals.NrLeads, nMinX, nMinY, out nMaxX, out nMaxY);

					ret = DrawSignal(myGraphics, signals, DateTime.MinValue, false, nTime, fmm_Per_s, fmm_Per_mV, nMinX, nMinY, nMaxX, nMaxY, fPixel_Per_ms * 1000f, fPixel_Per_uV, fLeadYSpace, bAllowResample);
				}
					break;
				case ECGDrawType.SixXTwo:
				{
					drawSections = new ECGDrawSection[18];

					int a = nTime,
						b = (5 * signals.RhythmSamplesPerSecond) + nTime,
						c = (10 * signals.RhythmSamplesPerSecond) + nTime;

					drawSections[ 0] = new ECGDrawSection(true, fmm_Per_mV, 0.0f,  2.5f * fGridY, signals.RhythmSamplesPerSecond, 2);
					drawSections[ 1] = new ECGDrawSection(true, fmm_Per_mV, 0.0f,  8.0f * fGridY, signals.RhythmSamplesPerSecond, 2);
					drawSections[ 2] = new ECGDrawSection(true, fmm_Per_mV, 0.0f, 13.5f * fGridY, signals.RhythmSamplesPerSecond, 2);
					drawSections[ 3] = new ECGDrawSection(true, fmm_Per_mV, 0.0f, 19.0f * fGridY, signals.RhythmSamplesPerSecond, 2);
					drawSections[ 4] = new ECGDrawSection(true, fmm_Per_mV, 0.0f, 24.5f * fGridY, signals.RhythmSamplesPerSecond, 2);
					drawSections[ 5] = new ECGDrawSection(true, fmm_Per_mV, 0.0f, 30.0f * fGridY, signals.RhythmSamplesPerSecond, 2);

					drawSections[ 6] = new ECGDrawSection(true, fmm_Per_mV,  2 * fGridX,  2.5f * fGridY, signals[ 0].Type, signals.RhythmAVM, signals.RhythmSamplesPerSecond, a, b, signals[ 0].Rhythm);
					drawSections[ 7] = new ECGDrawSection(true, fmm_Per_mV,  2 * fGridX,  8.0f * fGridY, signals[ 1].Type, signals.RhythmAVM, signals.RhythmSamplesPerSecond, a, b, signals[ 1].Rhythm);
					drawSections[ 8] = new ECGDrawSection(true, fmm_Per_mV,  2 * fGridX, 13.5f * fGridY, signals[ 2].Type, signals.RhythmAVM, signals.RhythmSamplesPerSecond, a, b, signals[ 2].Rhythm);
					drawSections[ 9] = new ECGDrawSection(true, fmm_Per_mV,  2 * fGridX, 19.0f * fGridY, signals[ 3].Type, signals.RhythmAVM, signals.RhythmSamplesPerSecond, a, b, signals[ 3].Rhythm);
					drawSections[10] = new ECGDrawSection(true, fmm_Per_mV,  2 * fGridX, 24.5f * fGridY, signals[ 4].Type, signals.RhythmAVM, signals.RhythmSamplesPerSecond, a, b, signals[ 4].Rhythm);
					drawSections[11] = new ECGDrawSection(true, fmm_Per_mV,  2 * fGridX, 30.0f * fGridY, signals[ 5].Type, signals.RhythmAVM, signals.RhythmSamplesPerSecond, a, b, signals[ 5].Rhythm);

					drawSections[12] = new ECGDrawSection(true, fmm_Per_mV, 27 * fGridX,  2.5f * fGridY, signals[ 6].Type, signals.RhythmAVM, signals.RhythmSamplesPerSecond, b, c, signals[ 6].Rhythm);
					drawSections[13] = new ECGDrawSection(true, fmm_Per_mV, 27 * fGridX,  8.0f * fGridY, signals[ 7].Type, signals.RhythmAVM, signals.RhythmSamplesPerSecond, b, c, signals[ 7].Rhythm);
					drawSections[14] = new ECGDrawSection(true, fmm_Per_mV, 27 * fGridX, 13.5f * fGridY, signals[ 8].Type, signals.RhythmAVM, signals.RhythmSamplesPerSecond, b, c, signals[ 8].Rhythm);
					drawSections[15] = new ECGDrawSection(true, fmm_Per_mV, 27 * fGridX, 19.0f * fGridY, signals[ 9].Type, signals.RhythmAVM, signals.RhythmSamplesPerSecond, b, c, signals[ 9].Rhythm);
					drawSections[16] = new ECGDrawSection(true, fmm_Per_mV, 27 * fGridX, 24.5f * fGridY, signals[10].Type, signals.RhythmAVM, signals.RhythmSamplesPerSecond, b, c, signals[10].Rhythm);
					drawSections[17] = new ECGDrawSection(true, fmm_Per_mV, 27 * fGridX, 30.0f * fGridY, signals[11].Type, signals.RhythmAVM, signals.RhythmSamplesPerSecond, b, c, signals[11].Rhythm);
				}
					break;
				case ECGDrawType.ThreeXFour:
				{
					drawSections = new ECGDrawSection[15];

					int	a = nTime,
						b = (int) (2.5f * signals.RhythmSamplesPerSecond) + nTime,
						c = (5 * signals.RhythmSamplesPerSecond) + nTime,
						d = (int) (7.5f * signals.RhythmSamplesPerSecond) + nTime,
						e = (10 * signals.RhythmSamplesPerSecond) + nTime;

					drawSections[ 0] = new ECGDrawSection(true, fmm_Per_mV, 0.0f,  5.0f * fGridY, signals.RhythmSamplesPerSecond, 2);
					drawSections[ 1] = new ECGDrawSection(true, fmm_Per_mV, 0.0f, 16.0f * fGridY, signals.RhythmSamplesPerSecond, 2);
					drawSections[ 2] = new ECGDrawSection(true, fmm_Per_mV, 0.0f, 27.0f * fGridY, signals.RhythmSamplesPerSecond, 2);

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?