示例#1
0
        /// <summary>
        /// Generates several sub graphs with progressively fewer number of data points
        /// This allows us to redraw the graph quickly during manipulation
        /// </summary>
        private void GenerateSubGraphs()
        {
            if (GraphData != null)
            {
                // Determine how many sub graphs we need
                int numGraphs     = 1;
                int currNumPoints = GraphData.Count;
                while (currNumPoints > 64)
                {
                    currNumPoints = currNumPoints >> 1;
                    numGraphs++;
                }

                // Create empty sub graphs
                graphData     = new List <PointF> [numGraphs];
                currNumPoints = GraphData.Count;
                for (int i = 0; i < graphData.Length; i++)
                {
                    graphData[i]  = new List <PointF>(currNumPoints);
                    currNumPoints = currNumPoints % 2 == 0 ? currNumPoints >> 1 : currNumPoints >> 1 + 1;
                }

                // This is the source of the graph's efficiency, here we take the users input and generate several other
                // data inputs with progressively less accurate (due to rounding) depictions of the graph data, but each
                // with 1/2 as many points as the last graph we generated.
                float[] totalX = new float[graphData.Length];
                float[] totalY = new float[graphData.Length];
                float   lastX  = float.MinValue;
                for (int i = 0; i < GraphData.Count; i++)
                {
                    IGraphData point       = GraphData[i];
                    float      x           = (float)point.GetX();
                    float      y           = (float)WorldToScreenYCoord(point.GetY());
                    bool       isLastPoint = i == GraphData.Count - 1;

                    if (x < lastX)
                    {
                        throw new ArgumentException("GraphData must be sorted by ascending X values");
                    }
                    lastX = x;

                    // Add the first and last points to all graphData sets
                    if (i == 0)
                    {
                        for (int j = 1; j < graphData.Length; j++)
                        {
                            graphData[j].Add(new PointF(x, y));
                        }
                    }

                    graphData[0].Add(new PointF(x, y));         // Add all data points to the first graphData set
                    for (int j = 1; j < graphData.Length; j++)  // For the rest of the sets, add averages of the points
                    {
                        totalX[j] += x;
                        totalY[j] += y;

                        // We are dealing with powers of 2, so we can do a more efficient mod operation '%'
                        int mask      = (1 << j) - 1;
                        int remainder = (mask & i);
                        if (remainder == 0 || isLastPoint)
                        {
                            int divisor = remainder == 0 ? mask + 1 : remainder;
                            graphData[j].Add(new PointF(totalX[j] / divisor, totalY[j] / divisor));
                            totalX[j] = totalY[j] = 0;
                        }
                    }
                }
            }
        }