📄 drmplot.cpp
字号:
RoundJoin));
}
void CDRMPlot::SetPSD(CVector<_REAL>& vecrData, CVector<_REAL>& vecrScale)
{
/* First check if plot must be set up */
if (InitCharType != POWER_SPEC_DENSITY)
{
InitCharType = POWER_SPEC_DENSITY;
SetupPSD();
}
/* Set actual data */
SetData(vecrData, vecrScale);
replot();
}
void CDRMPlot::SetupSNRSpectrum()
{
/* Init chart for power spectram density estimation */
setTitle(tr("SNR Spectrum (Weighted MER on MSC Cells)"));
enableAxis(QwtPlot::yRight, FALSE);
enableGridX(TRUE);
enableGridY(TRUE);
setAxisTitle(QwtPlot::xBottom, tr("Carrier Index"));
enableAxis(QwtPlot::yLeft, TRUE);
setAxisTitle(QwtPlot::yLeft, tr("WMER [dB]"));
canvas()->setBackgroundMode(QWidget::PaletteBackground);
/* Add main curve */
clear();
main1curve = insertCurve(tr("SNR Spectrum"));
/* Curve color */
setCurvePen(main1curve, QPen(MainPenColorPlot, 2, SolidLine, RoundCap,
RoundJoin));
}
void CDRMPlot::SetSNRSpectrum(CVector<_REAL>& vecrData,
CVector<_REAL>& vecrScale)
{
/* First check if plot must be set up */
if (InitCharType != SNR_SPECTRUM)
{
InitCharType = SNR_SPECTRUM;
SetupSNRSpectrum();
}
const int iSize = vecrScale.Size();
/* Fixed scale for x-axis */
setAxisScale(QwtPlot::xBottom, (double) 0.0, (double) iSize);
/* Fixed / variable scale (if SNR is in range, use fixed scale otherwise
enlarge scale) */
/* Get maximum value */
_REAL rMaxSNR = -_MAXREAL;
for (int i = 0; i < iSize; i++)
{
if (vecrData[i] > rMaxSNR)
rMaxSNR = vecrData[i];
}
double dMaxScaleYAxis = MAX_VAL_SNR_SPEC_Y_AXIS_DB;
if (rMaxSNR > dMaxScaleYAxis)
{
const double rEnlareStep = (double) 10.0; /* dB */
dMaxScaleYAxis = ceil(rMaxSNR / rEnlareStep) * rEnlareStep;
}
/* Set scale */
setAxisScale(QwtPlot::yLeft, MIN_VAL_SNR_SPEC_Y_AXIS_DB, dMaxScaleYAxis);
/* Set actual data */
SetData(vecrData, vecrScale);
replot();
}
void CDRMPlot::SetupInpSpec()
{
/* Init chart for power spectram density estimation */
setTitle(tr("Input Spectrum"));
enableAxis(QwtPlot::yRight, FALSE);
enableGridX(TRUE);
enableGridY(TRUE);
setAxisTitle(QwtPlot::xBottom, tr("Frequency [kHz]"));
enableAxis(QwtPlot::yLeft, TRUE);
setAxisTitle(QwtPlot::yLeft, tr("Input Spectrum [dB]"));
canvas()->setBackgroundMode(QWidget::PaletteBackground);
/* Fixed scale */
setAxisScale(QwtPlot::xBottom,
(double) 0.0, (double) SOUNDCRD_SAMPLE_RATE / 2000);
setAxisScale(QwtPlot::yLeft, MIN_VAL_INP_SPEC_Y_AXIS_DB,
MAX_VAL_INP_SPEC_Y_AXIS_DB);
/* Insert line for DC carrier */
clear();
curve1 = insertCurve(tr("DC carrier"));
setCurvePen(curve1, QPen(SpecLine1ColorPlot, 1, DotLine));
/* Add main curve */
main1curve = insertCurve(tr("Input spectrum"));
/* Curve color */
setCurvePen(main1curve, QPen(MainPenColorPlot, 1, SolidLine, RoundCap,
RoundJoin));
}
void CDRMPlot::SetInpSpec(CVector<_REAL>& vecrData, CVector<_REAL>& vecrScale,
const _REAL rDCFreq)
{
/* First check if plot must be set up */
if (InitCharType != INPUTSPECTRUM_NO_AV)
{
InitCharType = INPUTSPECTRUM_NO_AV;
SetupInpSpec();
}
/* Insert line for DC carrier */
double dX[2], dY[2];
dX[0] = dX[1] = rDCFreq / 1000;
/* Take the min-max values from scale to get vertical line */
dY[0] = MIN_VAL_INP_SPEC_Y_AXIS_DB;
dY[1] = MAX_VAL_INP_SPEC_Y_AXIS_DB;
setCurveData(curve1, dX, dY, 2);
/* Insert actual spectrum data */
SetData(vecrData, vecrScale);
replot();
}
void CDRMPlot::SetupInpPSD()
{
int i;
double dX[2], dY[2];
/* Init chart for power spectram density estimation */
setTitle(tr("Input PSD"));
enableAxis(QwtPlot::yRight, FALSE);
enableGridX(FALSE);
enableGridY(FALSE);
setAxisTitle(QwtPlot::xBottom, tr("Frequency [kHz]"));
enableAxis(QwtPlot::yLeft, TRUE);
setAxisTitle(QwtPlot::yLeft, tr("Input PSD [dB]"));
canvas()->setBackgroundMode(QWidget::PaletteBackground);
/* Fixed scale */
const double dXScaleMax = (double) SOUNDCRD_SAMPLE_RATE / 2000;
setAxisScale(QwtPlot::xBottom, (double) 0.0, dXScaleMax);
setAxisScale(QwtPlot::yLeft, MIN_VAL_INP_SPEC_Y_AXIS_DB,
MAX_VAL_INP_SPEC_Y_AXIS_DB);
/* Insert line for bandwidth marker */
clear();
curve1 = insertCurve(tr("Filter bandwidth"));
/* Make sure that line is bigger than the current plots height. Do this by
setting the width to a very large value. TODO: better solution */
setCurvePen(curve1, QPen(PassBandColorPlot, 10000));
/* Since we want to have the "filter bandwidth" bar behind the grid, we have
to draw our own grid after the previous curve was inserted. TODO: better
solution */
/* y-axis: get major ticks */
const int iNumMajTicksYAx = axisScale(QwtPlot::yLeft)->majCnt();
/* Make sure the grid does not end close to the border of the canvas.
Introduce some "margin" */
dX[0] = -dXScaleMax;
dX[1] = dXScaleMax + dXScaleMax;
/* Draw the grid for y-axis */
for (i = 0; i < iNumMajTicksYAx; i++)
{
const long curvegrid = insertCurve(tr("My Grid"));
setCurvePen(curvegrid, QPen(MainGridColorPlot, 0, DotLine));
dY[0] = dY[1] = axisScale(QwtPlot::yLeft)->majMark(i);
setCurveData(curvegrid, dX, dY, 2);
}
/* x-axis: get major ticks */
const int iNumMajTicksXAx = axisScale(QwtPlot::xBottom)->majCnt();
/* Make sure the grid does not end close to the border of the canvas.
Introduce some "margin" */
const double dDiffY =
MAX_VAL_INP_SPEC_Y_AXIS_DB - MIN_VAL_INP_SPEC_Y_AXIS_DB;
dY[0] = MIN_VAL_INP_SPEC_Y_AXIS_DB - dDiffY;
dY[1] = MAX_VAL_INP_SPEC_Y_AXIS_DB + dDiffY;
/* Draw the grid for x-axis */
for (i = 0; i < iNumMajTicksXAx; i++)
{
const long curvegrid = insertCurve(tr("My Grid"));
setCurvePen(curvegrid, QPen(MainGridColorPlot, 0, DotLine));
dX[0] = dX[1] = axisScale(QwtPlot::xBottom)->majMark(i);
setCurveData(curvegrid, dX, dY, 2);
}
/* Insert line for DC carrier */
curve2 = insertCurve(tr("DC carrier"));
setCurvePen(curve2, QPen(SpecLine1ColorPlot, 1, DotLine));
/* Add main curve */
main1curve = insertCurve(tr("Input PSD"));
/* Curve color */
setCurvePen(main1curve, QPen(MainPenColorPlot, 2, SolidLine, RoundCap,
RoundJoin));
}
void CDRMPlot::SetInpPSD(CVector<_REAL>& vecrData, CVector<_REAL>& vecrScale,
const _REAL rDCFreq, const _REAL rBWCenter,
const _REAL rBWWidth)
{
/* First check if plot must be set up. The char type "INPUT_SIG_PSD_ANALOG"
has the same initialization as "INPUT_SIG_PSD" */
if (InitCharType != INPUT_SIG_PSD)
{
InitCharType = INPUT_SIG_PSD;
SetupInpPSD();
}
/* Insert line for DC carrier */
double dX[2], dY[2];
dX[0] = dX[1] = rDCFreq / 1000;
/* Take the min-max values from scale to get vertical line */
dY[0] = MIN_VAL_INP_SPEC_Y_AXIS_DB;
dY[1] = MAX_VAL_INP_SPEC_Y_AXIS_DB;
setCurveData(curve2, dX, dY, 2);
/* Insert marker for filter bandwidth if required */
if (rBWWidth != (_REAL) 0.0)
{
dX[0] = (rBWCenter - rBWWidth / 2) * SOUNDCRD_SAMPLE_RATE / 1000;
dX[1] = (rBWCenter + rBWWidth / 2) * SOUNDCRD_SAMPLE_RATE / 1000;
/* Take the min-max values from scale to get vertical line */
dY[0] = MIN_VAL_INP_SPEC_Y_AXIS_DB;
dY[1] = MIN_VAL_INP_SPEC_Y_AXIS_DB;
setCurveData(curve1, dX, dY, 2);
}
else
setCurveData(curve1, NULL, NULL, 0);
/* Insert actual spectrum data */
SetData(vecrData, vecrScale);
replot();
}
void CDRMPlot::SetupInpSpecWaterf()
{
setTitle(tr("Waterfall Input Spectrum"));
enableAxis(QwtPlot::yRight, FALSE);
enableGridX(FALSE);
enableGridY(FALSE);
setAxisTitle(QwtPlot::xBottom, tr("Frequency [kHz]"));
enableAxis(QwtPlot::yLeft, FALSE);
/* Fixed scale */
setAxisScale(QwtPlot::xBottom,
(double) 0.0, (double) SOUNDCRD_SAMPLE_RATE / 2000);
/* Clear old plot data */
clear();
/* Clear background */
LastCanvasSize = canvas()->size(); /* Initial canvas size */
QPixmap Canvas(LastCanvasSize);
Canvas.fill(backgroundColor());
canvas()->setBackgroundPixmap(Canvas);
}
void CDRMPlot::SetInpSpecWaterf(CVector<_REAL>& vecrData,
CVector<_REAL>& vecrScale)
{
int i, iStartScale, iEndScale;
/* First check if plot must be set up */
if (InitCharType != INP_SPEC_WATERF)
{
InitCharType = INP_SPEC_WATERF;
SetupInpSpecWaterf();
}
/* Calculate sizes */
const QSize CanvSize = canvas()->size();
int iLenScale = axisScaleDraw(QwtPlot::xBottom)->length();
if ((iLenScale > 0) && (iLenScale < CanvSize.width()))
{
/* Calculate start and end of scale (needed for the borders) */
iStartScale =
(int) Floor(((_REAL) CanvSize.width() - iLenScale) / 2) - 1;
iEndScale = iLenScale + iStartScale;
}
else
{
/* Something went wrong, use safe parameters */
iStartScale = 0;
iEndScale = CanvSize.width();
iLenScale = CanvSize.width();
}
/* Move complete block one line further. Use old bitmap */
const QPixmap* pBPixmap = canvas()->backgroundPixmap();
QPixmap Canvas(CanvSize);
/* In case the canvas size has changed or there is no bitmap, reset
background */
if ((pBPixmap == NULL) || (LastCanvasSize != CanvSize))
Canvas.fill(backgroundColor());
else
{
bitBlt(&Canvas, 0, 1, pBPixmap, 0, 0,
CanvSize.width(), CanvSize.height() - 1, Qt::CopyROP);
}
/* Store current canvas size */
LastCanvasSize = CanvSize;
/* Paint new line (top line) */
QPainter Painter;
Painter.begin(&Canvas);
/* Left of the scale (left border) */
for (i = 0; i < iStartScale; i++)
{
/* Generate pixel */
Painter.setPen(backgroundColor());
Painter.drawPoint(i, 0); /* line 0 -> top line */
}
/* Actual waterfall data */
for (i = iStartScale; i < iEndScale; i++)
{
/* Init some constants */
const int iMaxHue = 359; /* Range of "Hue" is 0-359 */
const int iMaxSat = 255; /* Range of saturation is 0-255 */
/* Stretch width to entire canvas width */
const int iCurIdx =
(int) Round((_REAL) (i - iStartScale) / iLenScale * vecrData.Size());
/* Translate dB-values in colors */
const int iCurCol =
(int) Round((vecrData[iCurIdx] - MIN_VAL_INP_SPEC_Y_AXIS_DB) /
(MAX_VAL_INP_SPEC_Y_AXIS_DB - MIN_VAL_INP_SPEC_Y_AXIS_DB) *
iMaxHue);
/* Reverse colors and add some offset (to make it look a bit nicer) */
const int iColOffset = 60;
int iFinalCol = iMaxHue - iColOffset - iCurCol;
if (iFinalCol < 0) /* Prevent from out-of-range */
iFinalCol = 0;
/* Also change saturation to get dark colors when low level */
const int iCurSat = (int) ((1 - (_REAL) iFinalCol / iMaxHue) * iMaxSat);
/* Generate pixel */
Painter.setPen(QColor(iFinalCol, iCurSat, iCurSat, QColor::Hsv));
Painter.drawPoint(i, 0); /* line 0 -> top line */
}
/* Right of scale (right border) */
for (i = iEndScale; i < CanvSize.width(); i++)
{
/* Generate pixel */
Painter.setPen(backgroundColor());
Painter.drawPoint(i, 0); /* line 0 -> top line */
}
Painter.end();
/* Show the bitmap */
canvas()->setBackgroundPixmap(Canvas);
replot();
}
void CDRMPlot::SetupFACConst()
{
/* Init chart for FAC constellation */
setTitle(tr("FAC Constellation"));
enableAxis(QwtPlot::yRight, FALSE);
enableGridX(FALSE);
enableGridY(FALSE);
setAxisTitle(QwtPlot::xBottom, tr("Real"));
enableAxis(QwtPlot::yLeft, TRUE);
setAxisTitle(QwtPlot::yLeft, tr("Imaginary"));
canvas()->setBackgroundMode(QWidget::PaletteBackground);
/* Fixed scale (2 / sqrt(2)) */
setAxisScale(QwtPlot::xBottom, (double) -1.4142, (double) 1.4142);
setAxisScale(QwtPlot::yLeft, (double) -1.4142, (double) 1.4142);
/* Set marker symbol */
MarkerSym1.setStyle(QwtSymbol::Ellipse);
MarkerSym1.setSize(4);
MarkerSym1.setPen(QPen(MainPenColorConst));
MarkerSym1.setBrush(QBrush(MainPenColorConst));
/* Insert grid */
clear();
SetQAM4Grid();
}
void CDRMPlot::SetFACConst(CVector<_COMPLEX>& veccData)
{
/* First check if plot must be set up */
if (InitCharType != FAC_CONSTELLATION)
{
InitCharType = FAC_CONSTELLATION;
SetupFACConst();
}
removeMarkers();
SetData(veccData);
replot();
}
void CDRMPlot::SetupSDCConst(const CParameter::ECodScheme eNewCoSc)
{
/* Init chart for SDC constellation */
setTitle(tr("SDC Constellation"));
enableAxis(QwtPlot::yRight, FALSE);
enableGridX(FALSE);
enableGridY(FALSE);
setAxisTitle(QwtPlot::xBottom, tr("Real"));
enableAxis(QwtPlot::yLeft, TRUE);
setAxisTitle(QwtPlot::yLeft, tr("Imaginary"));
canvas()->setBackgroundMode(QWidget::PaletteBackground);
/* Fixed scale (4 / sqrt(10)) */
setAxisScale(QwtPlot::xBottom, (double) -1.2649, (double) 1.2649);
setAxisScale(QwtPlot::yLeft, (double) -1.2649, (double) 1.2649);
/* Insert grid */
clear();
if (eNewCoSc == CParameter::CS_1_SM)
SetQAM4Grid();
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -