ecgdraw.cs

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

CS
1,206
字号
				nMaxY = nMinY + (int) Math.Round(fGridY * nBoxesY),
				nAlternate = 1;

			if ((nMaxX > myGraphics.VisibleClipBounds.Width)
			||	(nMaxY > myGraphics.VisibleClipBounds.Height))
				return false;

			if (DisplayGrid == GridType.None)
				return true;

			Pen gridPen = new Pen(GraphColor, fPenWidth >= 1.0f ? fPenWidth : 1.0f),
				gridSecondPen = new Pen(GraphSecondColor, fPenWidth >= 1.0f ? fPenWidth : 1.0f);

			Brush gridBrush = null;

			if ((DisplayGrid == GridType.OneMillimeters)
			&&	(fGridX >= 10f)
			&&	(fGridY >= 10f))
			{
				fGridX /= 5;
				fGridY /= 5;
				
				nAlternate = 5;
			}
			else if (DisplayGrid == GridType.OneMillimeters)
			{
				gridBrush = new HatchBrush(HatchStyle.Percent30, GraphSecondColor, BackColor);
			}
			
			if (gridBrush != null)
				myGraphics.FillRectangle(gridBrush, nMinX, nMinY, nMaxX, nMaxY);

			int j = 0;
			
			// draw vertical lines.
			for (float i=nMinX;i <= (nMaxX + fPenWidth);i+=fGridX,j++)
			{
				int nTempX = (int) Math.Round(i);
				myGraphics.DrawLine((j % nAlternate) == 0 ? gridPen : gridSecondPen, nTempX, nMinY, nTempX, nMaxY);
			}

			j = 0;

			// draw horizontal lines.
			for (float i=nMinY;i <= (nMaxY + fPenWidth);i+=fGridY,j++)
			{
				int nTempY = (int) Math.Round(i);
				myGraphics.DrawLine((j % nAlternate) == 0 ? gridPen : gridSecondPen, nMinX, nTempY, nMaxX, nTempY);
			}

			if (gridBrush != null)
				gridBrush.Dispose();

			gridPen.Dispose();
			gridSecondPen.Dispose();

			return true;
		}
		/// <summary>
		/// Function that will draw as much signal on the image as possible.
		/// </summary>
		/// <param name="myGraphics">The drawing surface.</param>
		/// <param name="signals">signal data.</param>
		/// <param name="dtRecordTime">Recording time of signal.</param>
		/// <param name="bShowTime">true if need to show the time</param>
		/// <param name="nTime">Sample number to start drawing of signal,</param>
		/// <param name="fmm_Per_s">mm per second</param>
		/// <param name="fmm_Per_mV">mm per mV</param>
		/// <param name="nMinX">minimal X value to draw.</param>
		/// <param name="nMinY">minimal Y value to draw.</param>
		/// <param name="nMaxX">maximum X value to draw.</param>
		/// <param name="nMaxY">maximum Y value to draw.</param>
		/// <param name="fPixel_Per_s">pixels per second.</param>
		/// <param name="fPixel_Per_uV">pixels per uV.</param>
		/// <param name="fLeadYSpace">space for each lead.</param>
		/// <param name="bAllowResample">True if resample of signal is allowed.</param>
		/// <returns>Sample number to start next draw ECG on.</returns>
		private static int DrawSignal(Graphics myGraphics, ECGSignals.Signals signals, DateTime dtRecordTime, bool bShowTime, int nTime, float fmm_Per_s, float fmm_Per_mV, int nMinX, int nMinY, int nMaxX, int nMaxY, float fPixel_Per_s, float fPixel_Per_uV, float fLeadYSpace, bool bAllowResample)
		{
			float fGridY = (DpiY * Inch_Per_mm) * _mm_Per_GridLine;

			int nOldRhythmSamplesPerSecond = 0;

			// begin: resample signals to fit. (using a dirty solution)
			if (signals.RhythmSamplesPerSecond != (int) fPixel_Per_s)
			{
				if (!bAllowResample)
				{
					nOldRhythmSamplesPerSecond = 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;
			}
			// end: resample signals to fit. (dirty solution)

			// begin: find start and end.
			int nStart	= int.MaxValue,
				nEnd	= int.MinValue;

			for (int lead=0;lead < signals.NrLeads;lead++)
			{
				if (signals[lead] != null)
				{
					nStart = Math.Min(nStart, signals[lead].RhythmStart);
					nEnd = Math.Max(nEnd, signals[lead].RhythmEnd);
				}
			}
			// end: find start and end.

			int nPulseSpace = (int) Math.Floor(DpiX * Inch_Per_mm * _mm_Per_GridLine) + 1;

			nStart += nTime;

			int nXOffset = nMinX;
			float fYOffset = nMinY;

			DrawLeadHead(myGraphics, signals, dtRecordTime, bShowTime, nTime, nMinX, fYOffset, nMaxX, fmm_Per_s, fmm_Per_mV, fPixel_Per_uV, fLeadYSpace, nPulseSpace, nMinY);

			Pen myPen = new Pen(SignalColor);

			// begin: write rhythm data to image
			for (int n=nTime+1;n <= nEnd;n++)
			{
				for (byte i=0;i < signals.NrLeads;i++)
				{
					int	x1 = n - nStart - 1 + nPulseSpace + nXOffset,
						x2 = n - nStart + nPulseSpace + nXOffset;
					short
						y1 = short.MinValue,
						y2 = short.MinValue;

					if (x2 > nMaxX)
					{
						// check whether there is space for drawing leads below
						if ((int) (fYOffset + ((signals.NrLeads * fLeadYSpace + fGridY) * 2)) < nMaxY)
						{
							nXOffset -= nMaxX - nMinX - nPulseSpace;
							fYOffset += signals.NrLeads * fLeadYSpace + nMinY + fGridY;

							x1 = n - nStart - 1 + nPulseSpace + nXOffset;
							x2 = n - nStart + nPulseSpace + nXOffset;

							DrawLeadHead(myGraphics, signals, dtRecordTime, bShowTime, n-1, nMinX, fYOffset, nMaxX, fmm_Per_s, fmm_Per_mV, fPixel_Per_uV, fLeadYSpace, nPulseSpace, nMinY);
						}
						else
						{
							// no more space so end drawing.
							nEnd = n - 1;
							break;
						}
					}

					if ((n > signals[i].RhythmStart)
					&&	(n <= signals[i].RhythmEnd))
					{
						y1 = signals[i].Rhythm[n-1-signals[i].RhythmStart];
						y2 = signals[i].Rhythm[n-signals[i].RhythmStart];
					}

					if ((y1 != short.MinValue)
					&&	(y2 != short.MinValue))
						myGraphics.DrawLine(
							myPen,
							x1,
							(float) (((i + .5f) * fLeadYSpace) + fGridY - (y1 * signals.RhythmAVM * fPixel_Per_uV) + fYOffset),
							x2,
							(float) (((i + .5f) * fLeadYSpace) + fGridY - (y2 * signals.RhythmAVM * fPixel_Per_uV) + fYOffset));
				}
			}
			// end: write rhythm data to image

			if (nOldRhythmSamplesPerSecond != 0)
			{
				nEnd = (int) (((long) nEnd * nOldRhythmSamplesPerSecond) / signals.RhythmSamplesPerSecond);
			}

			myPen.Dispose();

			return nEnd;
		}
		/// <summary>
		/// Function to draw the head of a signal.
		/// </summary>
		/// <param name="myGraphics">The drawing surface.</param>
		/// <param name="signals">signal data</param>
		/// <param name="dtRecordTime">start time of recording</param>
		/// <param name="bShowTime">true if need to show time</param>
		/// <param name="nTime">sample number currently add.</param>
		/// <param name="nX">x position in image</param>
		/// <param name="fY">y position in image</param>
		/// <param name="nMaxX">maximum x value</param>
		/// <param name="fmm_Per_s">mm per second</param>
		/// <param name="fmm_Per_mV">mm per mV</param>
		/// <param name="fPixel_Per_uV">Pixels per uV</param>
		/// <param name="fLeadYSpace">Space for lead in Y axe.</param>
		/// <param name="nPulseSpace">Space for the calibration pulse (in pixels)</param>
		/// <param name="nExtraSpace">Space for text (in pixels)</param>
		private static void DrawLeadHead(Graphics myGraphics, ECGSignals.Signals signals, DateTime dtRecordTime, bool bShowTime, int nTime, int nX, float fY, int nMaxX, float fmm_Per_s, float fmm_Per_mV, float fPixel_Per_uV, float fLeadYSpace, int nPulseSpace, int nExtraSpace)
		{
			int nY = (int) Math.Round(fY);

			// begin: write tags per lead. 
			Font fontText = new Font("Verdana", _TextSize);
			SolidBrush solidBrush = new SolidBrush(TextColor);

			long lTime = (nTime * 1000) / signals.RhythmSamplesPerSecond;

			DateTime dtTemp = dtRecordTime.AddMilliseconds(lTime);

			if (bShowTime)
			{
				myGraphics.DrawString(
					((dtTemp.Year > 100)
					?	 dtTemp.ToShortDateString() + " "
					:	 "")
					+	dtTemp.Hour.ToString("00") + ":"
					+	dtTemp.Minute.ToString("00") + ":"
					+	dtTemp.Second.ToString("00") + "."
					+	(dtTemp.Millisecond/100).ToString("0"),
					fontText,
					solidBrush,
					nX,
					nY - nExtraSpace);
			}

			if (DisplayInfo)
			{
				string tempInfo = fmm_Per_s + "mm/s, " + fmm_Per_mV + "mm/mV";

				myGraphics.DrawString(
					tempInfo,
					fontText,
					solidBrush,
					nMaxX - myGraphics.MeasureString(tempInfo, fontText).Width,
					nY - nExtraSpace);
			}

			nY = (int) Math.Round(fY + (DpiY * Inch_Per_mm * _mm_Per_GridLine));

			for (byte i=0;i < signals.NrLeads;i++)
				myGraphics.DrawString(
					(signals[i].Type != ECGConversion.ECGSignals.LeadType.Unknown
					?	signals[i].Type.ToString()
					:	"Channel " + (i + 1)),
					fontText,
					solidBrush,
					nX + nPulseSpace + 2.0f ,
					nY + 2.0f + i * fLeadYSpace);

			fontText.Dispose();
			fontText = new Font("System", _TextSize);

			fontText.Dispose();
			solidBrush.Dispose();
			// end: write tags per lead.

			// begin: draw pulse.
			Pen myPen = new Pen(SignalColor);

			for (int i=0;i < signals.NrLeads;i++)
			{
				int	a = ((nPulseSpace << 1) / 3) + nX,
					b = (int) Math.Round(((i + .5f) * fLeadYSpace) - (1000.0f * fPixel_Per_uV)) + nY,
					c = (int) Math.Round((i + .5f) * fLeadYSpace) + nY;
				
				myGraphics.DrawLine(myPen, a, c, a, b);
				myGraphics.DrawLine(myPen, a, b, nPulseSpace + nX, b);
				myGraphics.DrawLine(myPen, nPulseSpace + nX, c, nPulseSpace + nX, b);
			}

			myPen.Dispose();
			// end: draw pulse.
		}
	}
}

⌨️ 快捷键说明

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