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 + -
显示快捷键?