Exemplo n.º 1
0
        private void RenderDataSignal(Plottables.Signal signal)
        {
            // use the signal processing class to convert dense data to pixel column fills
            PixelColumn[] pxCols   = SignalToPixelConverter(signal, settings);
            Pen           linePen  = new Pen(signal.style.lineColor);
            Brush         brushPen = new SolidBrush(signal.style.lineColor);

            // disable anti-aliasing so art looks better
            var originalSmoothMode = gfxData.SmoothingMode;

            gfxData.SmoothingMode = System.Drawing.Drawing2D.SmoothingMode.HighSpeed;

            // for zoomed-in data, only individual points will be plotted
            var points = new List <Point>();

            // plot one column at a time
            int skippedColumns = 0;

            for (int i = 0; i < pxCols.Length; i++)
            {
                if (pxCols[i] == null)
                {
                    // this column contains no data
                    skippedColumns += 1;
                }
                else if (pxCols[i].min == pxCols[i].max)
                {
                    // this column contains a single pixel of data
                    gfxData.FillRectangle(brushPen, i, pxCols[i].min, 1, 1);
                }
                else
                {
                    // this column contains a span of data
                    Point pt1 = new Point(i, pxCols[i].min);
                    Point pt2 = new Point(i, pxCols[i].max);
                    gfxData.DrawLine(linePen, pt1, pt2);
                }

                // if this is a new data point, remember it
                if (i > 0 && pxCols[i] != null && pxCols[i - 1] != null && pxCols[i].iLeft > pxCols[i - 1].iLeft)
                {
                    points.Add(new Point(i, pxCols[i].min));
                }
            }

            // draw markers at each individual point if zoomed-in6
            if ((points.Count() + skippedColumns) < settings.dataPlotWidth / 3)
            {
                int ptSize = 2;
                foreach (var point in points)
                {
                    gfxData.FillEllipse(brushPen, point.X - ptSize, point.Y - ptSize, 2 * ptSize, 2 * ptSize);
                }
                //gfxData.DrawLines(linePen, points.ToArray());
            }

            // revert to how things were
            gfxData.SmoothingMode = originalSmoothMode;
        }
Exemplo n.º 2
0
        private PixelColumn[] SignalToPixelConverter(Plottables.Signal signal, Settings settings)
        {
            PixelColumn[] pxCols = new PixelColumn[settings.dataPlotWidth];

            // theoretical minimum pixel if X1 were drawn
            int dataMinPx = (int)(settings.axisX.pxPerUnit * (-settings.axisX.x1));

            // step column by column left to right
            for (int i = 0; i < settings.dataPlotWidth; i++)
            {
                // determine what index values of the signal correspond to this pixel column
                int iLeft  = (int)(settings.axisX.unitsPerPx * signal.sampleRateHz * (i - dataMinPx));
                int iRight = (int)(iLeft + settings.axisX.unitsPerPx * signal.sampleRateHz);

                // ensure indexes are valid and skip columns without data
                iLeft  = Math.Max(iLeft, 0);
                iRight = Math.Min(signal.ys.Length - 1, iRight);
                iRight = Math.Max(iRight, 0);
                if (iRight == 0)
                {
                    continue;
                }
                if (iRight < 0 || iLeft > iRight)
                {
                    continue;
                }

                // pull iLeft of this column to the same iRight as the last
                if (i > 0 && pxCols[i - 1] != null)
                {
                    iLeft = pxCols[i - 1].iRight - 1;
                }

                // determine vertical span of this range
                double valMin = ArraySubMin(signal.ys, iLeft, iRight);
                double valMax = ArraySubMax(signal.ys, iLeft, iRight);

                // TODO: make indexes perfect - they don't always match-up exactly
                //Console.WriteLine($"Index [{iLeft}:{iRight}] min/max = {valMin}/{valMax}");

                // convert this value to a pixel location on screen
                int pxMin = (int)((settings.axisY.x2 - valMin) * settings.axisY.pxPerUnit) + 1;
                int pxMax = (int)((settings.axisY.x2 - valMax) * settings.axisY.pxPerUnit) + 1;

                // populate the object
                pxCols[i] = new PixelColumn(pxMin, pxMax, iLeft, iRight);
            }

            return(pxCols);
        }