/// <summary>
        /// Will return the new root (unchanged except in start-up)
        /// </summary>
        public static VNode ProcessDataEvent(VDataEvent e, VNode Root, VoronoiGraph VG, double ys, out VDataNode[] CircleCheckList)
        {
            if (Root == null)
             {
            Root = new VDataNode(e.DataPoint);
            CircleCheckList = new VDataNode[] { (VDataNode)Root };
            return Root;
             }
             //1. Find the node to be replaced
             VNode C = VNode.FindDataNode(Root, ys, e.DataPoint[0]);
             //2. Create the subtree (ONE Edge, but two VEdgeNodes)
             VoronoiEdge VE = new VoronoiEdge();
             VE.LeftData = ((VDataNode)C).DataPoint;
             VE.RightData = e.DataPoint;
             VE.VVertexA = Fortune.VVUnkown;
             VE.VVertexB = Fortune.VVUnkown;
             VG.Edges.Add(VE);

             VNode SubRoot;
             if (Math.Abs(VE.LeftData[1] - VE.RightData[1]) < 1e-10)
             {
            if (VE.LeftData[0] < VE.RightData[0])
            {
               SubRoot = new VEdgeNode(VE, false);
               SubRoot.Left = new VDataNode(VE.LeftData);
               SubRoot.Right = new VDataNode(VE.RightData);
            }
            else
            {
               SubRoot = new VEdgeNode(VE, true);
               SubRoot.Left = new VDataNode(VE.RightData);
               SubRoot.Right = new VDataNode(VE.LeftData);
            }
            CircleCheckList = new VDataNode[] { (VDataNode)SubRoot.Left, (VDataNode)SubRoot.Right };
             }
             else
             {
            SubRoot = new VEdgeNode(VE, false);
            SubRoot.Left = new VDataNode(VE.LeftData);
            SubRoot.Right = new VEdgeNode(VE, true);
            SubRoot.Right.Left = new VDataNode(VE.RightData);
            SubRoot.Right.Right = new VDataNode(VE.LeftData);
            CircleCheckList = new VDataNode[] { (VDataNode)SubRoot.Left, (VDataNode)SubRoot.Right.Left, (VDataNode)SubRoot.Right.Right };
             }

             //3. Apply subtree
             if (C.Parent == null)
            return SubRoot;
             C.Parent.Replace(C, SubRoot);
             return Root;
        }
        public static VoronoiGraph ComputeVoronoiGraph(IEnumerable Datapoints)
        {
            BinaryPriorityQueue PQ = new BinaryPriorityQueue();
             Hashtable CurrentCircles = new Hashtable();
             VoronoiGraph VG = new VoronoiGraph();
             VNode RootNode = null;
             foreach (Vector V in Datapoints)
             {
            PQ.Push(new VDataEvent(V));
             }
             while (PQ.Count > 0)
             {
            VEvent VE = PQ.Pop() 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.Push(VCE);
                  CurrentCircles[VD] = VCE;
               }
            }
            if (VE is VDataEvent)
            {
               Vector DP = ((VDataEvent)VE).DataPoint;
               foreach (VCircleEvent VCE in CurrentCircles.Values)
               {
                  if (MathTools.Dist(DP[0], DP[1], VCE.Center[0], VCE.Center[1]) < VCE.Y - VCE.Center[1] && Math.Abs(MathTools.Dist(DP[0], DP[1], VCE.Center[0], VCE.Center[1]) - (VCE.Y - VCE.Center[1])) > 1e-10)
                     VCE.Valid = false;
               }
            }
             }
             VNode.CleanUpTree(RootNode);
             foreach (VoronoiEdge VE in VG.Edges)
             {
            if (VE.Done)
               continue;
            if (VE.VVertexB == Fortune.VVUnkown)
            {
               VE.AddVertex(Fortune.VVInfinite);
               if (Math.Abs(VE.LeftData[1] - VE.RightData[1]) < 1e-10 && VE.LeftData[0] < VE.RightData[0])
               {
                  Vector T = VE.LeftData;
                  VE.LeftData = VE.RightData;
                  VE.RightData = T;
               }
            }
             }

             ArrayList MinuteEdges = new ArrayList();
             foreach (VoronoiEdge VE in VG.Edges)
             {
            if (!VE.IsPartlyInfinite && VE.VVertexA.Equals(VE.VVertexB))
            {
               MinuteEdges.Add(VE);
               // prevent rounding errors from expanding to holes
               foreach (VoronoiEdge VE2 in VG.Edges)
               {
                  if (VE2.VVertexA.Equals(VE.VVertexA))
                     VE2.VVertexA = VE.VVertexA;
                  if (VE2.VVertexB.Equals(VE.VVertexA))
                     VE2.VVertexB = VE.VVertexA;
               }
            }
             }
             foreach (VoronoiEdge VE in MinuteEdges)
            VG.Edges.Remove(VE);

             return VG;
        }
        public static VNode ProcessCircleEvent(VCircleEvent e, VNode Root, VoronoiGraph VG, double ys, out VDataNode[] CircleCheckList)
        {
            VDataNode a, b, c;
             VEdgeNode eu, eo;
             b = e.NodeN;
             a = VNode.LeftDataNode(b);
             c = VNode.RightDataNode(b);
             if (a == null || b.Parent == null || c == null || !a.DataPoint.Equals(e.NodeL.DataPoint) || !c.DataPoint.Equals(e.NodeR.DataPoint))
             {
            CircleCheckList = new VDataNode[] { };
            return Root; // Abbruch da sich der Graph verändert hat
             }
             eu = (VEdgeNode)b.Parent;
             CircleCheckList = new VDataNode[] { a, c };
             //1. Create the new Vertex
             Vector VNew = new Vector(e.Center[0], e.Center[1]);
             //			VNew[0] = Fortune.ParabolicCut(a.DataPoint[0],a.DataPoint[1],c.DataPoint[0],c.DataPoint[1],ys);
             //			VNew[1] = (ys + a.DataPoint[1])/2 - 1/(2*(ys-a.DataPoint[1]))*(VNew[0]-a.DataPoint[0])*(VNew[0]-a.DataPoint[0]);
             VG.Vertizes.Add(VNew);
             //2. Find out if a or c are in a distand part of the tree (the other is then b's sibling) and assign the new vertex
             if (eu.Left == b) // c is sibling
             {
            eo = VNode.EdgeToRightDataNode(a);

            // replace eu by eu's Right
            eu.Parent.Replace(eu, eu.Right);
             }
             else // a is sibling
             {
            eo = VNode.EdgeToRightDataNode(b);

            // replace eu by eu's Left
            eu.Parent.Replace(eu, eu.Left);
             }
             eu.Edge.AddVertex(VNew);
             //			///////////////////// uncertain
             //			if(eo==eu)
             //				return Root;
             //			/////////////////////

             //complete & cleanup eo
             eo.Edge.AddVertex(VNew);
             //while(eo.Edge.VVertexB == Fortune.VVUnkown)
             //{
             //    eo.Flipped = !eo.Flipped;
             //    eo.Edge.AddVertex(Fortune.VVInfinite);
             //}
             //if(eo.Flipped)
             //{
             //    Vector T = eo.Edge.LeftData;
             //    eo.Edge.LeftData = eo.Edge.RightData;
             //    eo.Edge.RightData = T;
             //}

             //2. Replace eo by new Edge
             VoronoiEdge VE = new VoronoiEdge();
             VE.LeftData = a.DataPoint;
             VE.RightData = c.DataPoint;
             VE.AddVertex(VNew);
             VG.Edges.Add(VE);

             VEdgeNode VEN = new VEdgeNode(VE, false);
             VEN.Left = eo.Left;
             VEN.Right = eo.Right;
             if (eo.Parent == null)
            return VEN;
             eo.Parent.Replace(eo, VEN);
             return Root;
        }
 public static VoronoiGraph FilterVG(VoronoiGraph VG, double minLeftRightDist)
 {
     VoronoiGraph VGErg = new VoronoiGraph();
      foreach (VoronoiEdge VE in VG.Edges)
      {
     if (Math.Sqrt(Vector.Dist(VE.LeftData, VE.RightData)) >= minLeftRightDist)
        VGErg.Edges.Add(VE);
      }
      foreach (VoronoiEdge VE in VGErg.Edges)
      {
     VGErg.Vertizes.Add(VE.VVertexA);
     VGErg.Vertizes.Add(VE.VVertexB);
      }
      return VGErg;
 }