/// <summary>
        /// Compares to a VEvent.
        /// </summary>
        /// <returns>
        /// The to.
        /// </returns>
        /// <param name='obj'>
        /// Object.
        /// </param>
        /// <exception cref='ArgumentException'>
        /// Is thrown when an argument passed to a method is invalid.
        /// </exception>
        public int CompareTo(object obj)
        {
            VEvent vObj = obj as VEvent;

            if (vObj == null)
            {
                throw new ArgumentException("obj not VEvent!");
            }

            int i = Y.CompareTo(vObj.Y);

            if (i != 0)
            {
                return(i);
            }

            return(X.CompareTo(vObj.X));
        }
        /// <summary>
        /// Computes the voronoi graph.
        /// </summary>
        /// <returns>
        /// The voronoi graph.
        /// </returns>
        /// <param name='Datapoints'>
        /// Datapoints.
        /// </param>
        /// <exception cref='Exception'>
        /// Represents errors that occur during application execution.
        /// </exception>
        public static VoronoiGraph ComputeVoronoiGraph(IEnumerable Datapoints)
        {
            PriorityQueue <VEvent> PQ   = new PriorityQueue <VEvent>(PriorityQueueType.Minimum);
            Hashtable    CurrentCircles = new Hashtable();
            VoronoiGraph VG             = new VoronoiGraph();
            VNode        RootNode       = null;

            foreach (Vector2D V in Datapoints)
            {
                PQ.Enqueue(new VDataEvent(V));
            }

            while (PQ.Count > 0)
            {
                VEvent      VE = PQ.Dequeue() as VEvent;
                VDataNode[] CircleCheckList;

                if (VE is VDataEvent)
                {
                    RootNode = VNode.ProcessDataEvent(VE as VDataEvent, RootNode, VG, VE.Y, out CircleCheckList);
                }
                else if (VE is VCircleEvent)
                {
                    CurrentCircles.Remove(((VCircleEvent)VE).NodeN);
                    if (!((VCircleEvent)VE).Valid)
                    {
                        continue;
                    }
                    RootNode = VNode.ProcessCircleEvent(VE as VCircleEvent, RootNode, VG, VE.Y, out CircleCheckList);
                }
                else
                {
                    throw new Exception("Got event of type " + VE.GetType().ToString() + "!");
                }

                foreach (VDataNode VD in CircleCheckList)
                {
                    if (CurrentCircles.ContainsKey(VD))
                    {
                        ((VCircleEvent)CurrentCircles[VD]).Valid = false;
                        CurrentCircles.Remove(VD);
                    }

                    VCircleEvent VCE = VNode.CircleCheckDataNode(VD, VE.Y);
                    if (VCE != null)
                    {
                        PQ.Enqueue(VCE);
                        CurrentCircles[VD] = VCE;
                    }
                }

                if (VE is VDataEvent)
                {
                    Vector2D DP = ((VDataEvent)VE).DataPoint;
                    foreach (VCircleEvent VCE in CurrentCircles.Values)
                    {
                        if (MathTools.Dist(DP.X, DP.Y, VCE.Center.X, VCE.Center.Y) < VCE.Y - VCE.Center.Y && Math.Abs(MathTools.Dist(DP.X, DP.Y, VCE.Center.X, VCE.Center.Y) - (VCE.Y - VCE.Center.Y)) > 1e-10)
                        {
                            VCE.Valid = false;
                        }
                    }
                }
            }

            return(VG);
        }