Beispiel #1
0
 /// <summary>
 /// Draws the graph. This single call updates the graph completely.
 /// </summary>
 /// Given a data access function which will return a double value for a given integer index of 0-entries this funtion will create
 /// a graph of the data using the color scheme previously set. This is a convenience method to simplify creating a graph with just
 /// one data line and a zero line.
 /// <param name="accessFunc">Access function which gives this method access to the data to graph.</param>
 /// <param name="max">Maximum value to be graphed.</param>
 /// <param name="min">Minimum value to be graphed.</param>
 /// <param name="entries">Number of entries accessible via the access function.</param>
 public void drawGraph(DataAccessFunc accessFunc, double max, double min, int entries)
 {
     reset();
     drawZeroLine(max, min, _zeroLine);
     drawLineOnGraph(accessFunc, max, min, entries, _lineColor);
     Apply();
 }
Beispiel #2
0
        /// <summary>
        /// Draws a line on graph.
        /// </summary>
        /// <param name="accessFunc">Access function which gives this method access to the data to graph.</param>
        /// <param name="max">Maximum value to be graphed.</param>
        /// <param name="min">Minimum value to be graphed.</param>
        /// <param name="entries">Number of entries accessible via the access function.</param>
        /// <param name="color">Color of this line.</param>
        public void drawLineOnGraph(DataAccessFunc accessFunc, double max, double min, int entries, Color color)
        {
            _dirty = true;
            double scale = (double)_image.height / (max - min);
            int average = 1;
            int remainder = 0;
            int offset = 0;
            // If there are more entries than the _image can display calculate how many entries we should average.
            // If the division is not even calculate how many entries we should skip over and how often.
            if (entries > _image.width) {
                average = entries / _image.width;
                remainder = entries % _image.width;
                if (remainder > 0) {
                    offset = (int)Math.Ceiling ((double)_image.width / (double)remainder);
                }
            }

            int prevY = 0;
            int index = 0;
            // For every x determine the range of ys that need to change and set them.
            for (int lx = 0; lx < _image.width;lx++) {
                double value = 0;

                // Don't exceed the boundaries of accessFunc.
                if (index + average > entries) {
                    break;
                }
                // Average some values if we have more values than we have width.
                for (int i = 0; i < average; i++) {
                    double data = accessFunc (index);
                    if (Double.IsNaN (data)) {
                        value = data;
                    }
                    value += data;
                    index++;
                }
                if (Double.IsNaN (value)) {
                    continue;
                }
                value /= average;

                // If we have too many entries and we can't easily average them drop values, but do it evenly so the holes aren't obvious.
                if (offset > 0 && lx % offset == 0 && remainder > 0) {
                    index++;
                    remainder--;
                }

                // Subtract min from the value to position it relative to y=0 and scale it to fit the image height. Cast it to an int.
                int y = (int)((value - min )* scale);

                // Calculate a contigous line from the previous y to the current position. This gives the graph an unbroken appearance.
                int startY = prevY;
                int endY = y;
                if (y < prevY) {
                    startY = y;
                    endY = prevY;
                }
                if (lx == 0) {
                    endY = y;
                    startY = y;
                }
                // Make sure the line is tall enough to be visible.
                if ((endY - startY) < _lineWidth) {
                    endY += (_lineWidth - (endY - startY));
                }
                // Never exceed the image height. We're dealing with floating point, so there is a certain inaccuracy in the scaling that
                // may allow our calculated y to exceed the image height by a pixel or two.
                if (endY > _image.height) {
                    endY = _image.height;
                    startY = _image.height - _lineWidth;
                }

                // Draw the line segment.
                for (int ly = startY; ly < endY; ly++)
                    _image.SetPixel(lx,ly,color);

                prevY = y;
            }
        }
Beispiel #3
0
 /// <summary>
 /// Draws the graph. This single call updates the graph completely.
 /// </summary>
 /// Given a data access function which will return a double value for a given integer index of 0-entries this funtion will create 
 /// a graph of the data using the color scheme previously set. This is a convenience method to simplify creating a graph with just
 /// one data line and a zero line.
 /// <param name="accessFunc">Access function which gives this method access to the data to graph.</param>
 /// <param name="max">Maximum value to be graphed.</param>
 /// <param name="min">Minimum value to be graphed.</param>
 /// <param name="entries">Number of entries accessible via the access function.</param>
 public void drawGraph(DataAccessFunc accessFunc, double max, double min, int entries)
 {
     reset ();
     drawZeroLine (max, min, _zeroLine);
     drawLineOnGraph (accessFunc, max, min, entries, _lineColor);
     Apply ();
 }
Beispiel #4
0
        /// <summary>
        /// Draws a line on graph.
        /// </summary>
        /// <param name="accessFunc">Access function which gives this method access to the data to graph.</param>
        /// <param name="max">Maximum value to be graphed.</param>
        /// <param name="min">Minimum value to be graphed.</param>
        /// <param name="entries">Number of entries accessible via the access function.</param>
        /// <param name="color">Color of this line.</param>
        public void drawLineOnGraph(DataAccessFunc accessFunc, double max, double min, int entries, Color color)
        {
            _dirty = true;
            double scale     = (double)_image.height / (max - min);
            int    average   = 1;
            int    remainder = 0;
            int    offset    = 0;

            // If there are more entries than the _image can display calculate how many entries we should average.
            // If the division is not even calculate how many entries we should skip over and how often.
            if (entries > _image.width)
            {
                average   = entries / _image.width;
                remainder = entries % _image.width;
                if (remainder > 0)
                {
                    offset = (int)Math.Ceiling((double)_image.width / (double)remainder);
                }
            }

            int prevY = 0;
            int index = 0;

            // For every x determine the range of ys that need to change and set them.
            for (int lx = 0; lx < _image.width; lx++)
            {
                double value = 0;

                // Don't exceed the boundaries of accessFunc.
                if (index + average > entries)
                {
                    break;
                }
                // Average some values if we have more values than we have width.
                for (int i = 0; i < average; i++)
                {
                    double data = accessFunc(index);
                    if (Double.IsNaN(data))
                    {
                        value = data;
                    }
                    value += data;
                    index++;
                }
                if (Double.IsNaN(value))
                {
                    continue;
                }
                value /= average;

                // If we have too many entries and we can't easily average them drop values, but do it evenly so the holes aren't obvious.
                if (offset > 0 && lx % offset == 0 && remainder > 0)
                {
                    index++;
                    remainder--;
                }

                // Subtract min from the value to position it relative to y=0 and scale it to fit the image height. Cast it to an int.
                int y = (int)((value - min) * scale);

                // Calculate a contigous line from the previous y to the current position. This gives the graph an unbroken appearance.
                int startY = prevY;
                int endY   = y;
                if (y < prevY)
                {
                    startY = y;
                    endY   = prevY;
                }
                if (lx == 0)
                {
                    endY   = y;
                    startY = y;
                }
                // Make sure the line is tall enough to be visible.
                if ((endY - startY) < _lineWidth)
                {
                    endY += (_lineWidth - (endY - startY));
                }
                // Never exceed the image height. We're dealing with floating point, so there is a certain inaccuracy in the scaling that
                // may allow our calculated y to exceed the image height by a pixel or two.
                if (endY > _image.height)
                {
                    endY   = _image.height;
                    startY = _image.height - _lineWidth;
                }

                // Draw the line segment.
                for (int ly = startY; ly < endY; ly++)
                {
                    _image.SetPixel(lx, ly, color);
                }

                prevY = y;
            }
        }