IEnumerable <IGraphDataNode> MinMaxFinalNodesInOrder(IGraphDataNode minNode, IGraphDataNode maxNode, IGraphDataNode finalNode)
        {
            if (minNode != null && maxNode != null && minNode != maxNode)
            {
                if (minNode.StartTime < maxNode.StartTime)
                {
                    yield return(minNode);

                    yield return(maxNode);
                }
                else
                {
                    yield return(maxNode);

                    yield return(minNode);
                }
            }
            else if (minNode != null)
            {
                yield return(minNode);
            }
            else if (maxNode != null)
            {
                yield return(maxNode);
            }

            if (finalNode != null)
            {
                yield return(finalNode);
            }
        }
        public IEnumerable <IGraphDataNode> GetNodesInTimespan(ulong startTime, ulong endTime, ulong granularity)
        {
            if (this.DataSource == null)
            {
                yield break;
            }

            IGraphDataNode firstNode = null;

            foreach (var node in SampleNodes(granularity))
            {
                if (node.StartTime >= endTime)
                {
                    if (firstNode != null)
                    {
                        yield return(firstNode);
                    }

                    yield return(node);

                    yield break;
                }

                if (node.StartTime < startTime)
                {
                    firstNode = node;
                    continue;
                }

                if (firstNode != null)
                {
                    yield return(firstNode);

                    firstNode = null;
                }

                yield return(node);
            }
        }
        IEnumerable <IGraphDataNode> SampleNodes(ulong granularity)
        {
            IGraphDataNode lastSampledNode = null;
            IGraphDataNode finalNode       = null;
            IGraphDataNode minNode         = null;
            IGraphDataNode maxNode         = null;

            foreach (var node in this.DataSource.Nodes)
            {
                if (lastSampledNode != null && node.StartTime - lastSampledNode.StartTime < granularity)
                {
                    finalNode = node;
                    if (maxNode == null || node.Y > maxNode.Y)
                    {
                        maxNode = node;
                    }
                    if (minNode == null || node.Y < minNode.Y)
                    {
                        minNode = node;
                    }
                    continue;
                }

                foreach (var minMaxNode in MinMaxFinalNodesInOrder(minNode, maxNode, node))
                {
                    yield return(minMaxNode);
                }

                lastSampledNode = node;
                finalNode       = null;
                minNode         = null;
                maxNode         = null;
            }

            foreach (var minMaxNode in MinMaxFinalNodesInOrder(minNode, maxNode, finalNode))
            {
                yield return(minMaxNode);
            }
        }
        IEnumerable<IGraphDataNode> MinMaxFinalNodesInOrder(IGraphDataNode minNode, IGraphDataNode maxNode, IGraphDataNode finalNode)
        {
            if (minNode != null && maxNode != null && minNode != maxNode)
            {
                if (minNode.StartTime < maxNode.StartTime)
                {
                    yield return minNode;
                    yield return maxNode;
                }
                else
                {
                    yield return maxNode;
                    yield return minNode;
                }
            }
            else if (minNode != null)
            {
                yield return minNode;
            }
            else if (maxNode != null)
            {
                yield return maxNode;
            }

            if (finalNode != null)
            {
                yield return finalNode;
            }
        }