/// <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);
        }
예제 #2
0
        /// <summary>
        /// Processes the circle event.
        /// </summary>
        /// <returns>
        /// The circle event.
        /// </returns>
        /// <param name='e'>
        /// E.
        /// </param>
        /// <param name='Root'>
        /// Root.
        /// </param>
        /// <param name='VG'>
        /// V.
        /// </param>
        /// <param name='ys'>
        /// Ys.
        /// </param>
        /// <param name='CircleCheckList'>
        /// Circle check list.
        /// </param>
        public static VNode ProcessCircleEvent(VCircleEvent e, VNode Root, VoronoiGraph VG, double ys, out VDataNode[] CircleCheckList)
        {
            VDataNode a;
            VDataNode b;
            VDataNode c;
            VEdgeNode eu;
            VEdgeNode 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 0/00ndert hat
            }

            eu = b.Parent as VEdgeNode;
            CircleCheckList = new VDataNode[] { a, c };

            //1. Create the new Vertex
            Vector2D VNew = new Vector2D(e.Center.X, e.Center.Y);

            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);
            eo.Edge.AddVertex(VNew);

            //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);
        }
예제 #3
0
        /// <summary>
        /// Will return the new root (unchanged except in start-up)
        /// </summary>
        /// <summary>
        /// Processes the data event.
        /// </summary>
        /// <returns>
        /// The data event.
        /// </returns>
        /// <param name='e'>
        /// E.
        /// </param>
        /// <param name='Root'>
        /// Root.
        /// </param>
        /// <param name='VG'>
        /// V.
        /// </param>
        /// <param name='ys'>
        /// Ys.
        /// </param>
        /// <param name='CircleCheckList'>
        /// Circle check list.
        /// </param>
        /// <exception cref='Exception'>
        /// Represents errors that occur during application execution.
        /// </exception>
        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[] { Root as VDataNode };
                return(Root);
            }

            //1. Find the node to be replaced
            VNode     C     = VNode.FindDataNode(Root, ys, e.DataPoint.X);
            VDataNode cData = C as VDataNode;

            if (cData == null)
            {
                throw new Exception("Can't cast to data node");
            }

            //2. Create the subtree (ONE Edge, but two VEdgeNodes)
            VoronoiEdge VE = new VoronoiEdge();

            VE.LeftData  = cData.DataPoint;
            VE.RightData = e.DataPoint;
            VE.VVertexA  = Fortune.VVUnkown;
            VE.VVertexB  = Fortune.VVUnkown;
            VG.Edges.Add(VE);

            VNode SubRoot;

            if (Math.Abs(VE.LeftData.Y - VE.RightData.Y) < 1e-10)
            {
                if (VE.LeftData.X < VE.RightData.X)
                {
                    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[] { SubRoot.Left as VDataNode, SubRoot.Right as VDataNode };
            }
            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[] { SubRoot.Left as VDataNode, SubRoot.Right.Left as VDataNode, SubRoot.Right.Right as VDataNode };
            }

            //3. Apply subtree
            if (C.Parent == null)
            {
                return(SubRoot);
            }

            C.Parent.Replace(C, SubRoot);

            return(Root);
        }
예제 #4
0
        /// <summary>
        /// Will return the new root (unchanged except in start-up)
        /// </summary>
        /// <summary>
        /// Processes the data event.
        /// </summary>
        /// <returns>
        /// The data event.
        /// </returns>
        /// <param name='e'>
        /// E.
        /// </param>
        /// <param name='Root'>
        /// Root.
        /// </param>
        /// <param name='VG'>
        /// V.
        /// </param>
        /// <param name='ys'>
        /// Ys.
        /// </param>
        /// <param name='CircleCheckList'>
        /// Circle check list.
        /// </param>
        /// <exception cref='Exception'>
        /// Represents errors that occur during application execution.
        /// </exception>
        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[] {Root as VDataNode};
                return Root;
            }

            //1. Find the node to be replaced
            VNode C = VNode.FindDataNode( Root, ys, e.DataPoint.X );
            VDataNode cData = C as VDataNode;

            if( cData == null ) {
                throw new Exception( "Can't cast to data node" );
            }

            //2. Create the subtree (ONE Edge, but two VEdgeNodes)
            VoronoiEdge VE = new VoronoiEdge();
            VE.LeftData = cData.DataPoint;
            VE.RightData = e.DataPoint;
            VE.VVertexA = Fortune.VVUnkown;
            VE.VVertexB = Fortune.VVUnkown;
            VG.Edges.Add( VE );

            VNode SubRoot;
            if( Math.Abs( VE.LeftData.Y - VE.RightData.Y ) < 1e-10 ) {
                if( VE.LeftData.X < VE.RightData.X ) {
                    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[] {SubRoot.Left as VDataNode, SubRoot.Right as VDataNode};
            } 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[] {SubRoot.Left as VDataNode, SubRoot.Right.Left as VDataNode, SubRoot.Right.Right as VDataNode};
            }

            //3. Apply subtree
            if( C.Parent == null ) {
                return SubRoot;
            }

            C.Parent.Replace( C, SubRoot );

            return Root;
        }
예제 #5
0
        /// <summary>
        /// Processes the circle event.
        /// </summary>
        /// <returns>
        /// The circle event.
        /// </returns>
        /// <param name='e'>
        /// E.
        /// </param>
        /// <param name='Root'>
        /// Root.
        /// </param>
        /// <param name='VG'>
        /// V.
        /// </param>
        /// <param name='ys'>
        /// Ys.
        /// </param>
        /// <param name='CircleCheckList'>
        /// Circle check list.
        /// </param>
        public static VNode ProcessCircleEvent( VCircleEvent e, VNode Root, VoronoiGraph VG, double ys, out VDataNode[] CircleCheckList )
        {
            VDataNode a;
            VDataNode b;
            VDataNode c;
            VEdgeNode eu;
            VEdgeNode 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 0/00ndert hat
            }

            eu = b.Parent as VEdgeNode;
            CircleCheckList = new VDataNode[] {a,c};

            //1. Create the new Vertex
            Vector2D VNew = new Vector2D( e.Center.X, e.Center.Y );

            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 );
            eo.Edge.AddVertex( VNew );

            //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;
        }
        /// <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;
        }