Пример #1
0
        // create a new site where the HalfEdges intersect
        private Site Intersect(HalfEdge firstHalfEdge, HalfEdge secondHalfEdge)
        {
            Edge edge;
            HalfEdge halfEdge;
            bool isRightOfSite; // vertex

            Edge firstEdge = firstHalfEdge.Edge;
            Edge secondEdge = secondHalfEdge.Edge;

            if (firstEdge == null || secondEdge == null)
            {
                return null;
            }

            // if the two edges bisect the same parent, return null
            if (firstEdge.Region[1] == secondEdge.Region[1])
            {
                return null;
            }

            double distance = (firstEdge.A * secondEdge.B) - (firstEdge.B * secondEdge.A);

            if (-1.0e-10 < distance && distance < 1.0e-10)
            {
                return null;
            }

            double intersectionPointX = ((firstEdge.C * secondEdge.B) - (secondEdge.C * firstEdge.B)) / distance;
            double intersectionPointY = ((secondEdge.C * firstEdge.A) - (firstEdge.C * secondEdge.A)) / distance;

            if ((firstEdge.Region[1].Coordinates.Y < secondEdge.Region[1].Coordinates.Y)
                || (firstEdge.Region[1].Coordinates.Y == secondEdge.Region[1].Coordinates.Y && 
                firstEdge.Region[1].Coordinates.X < secondEdge.Region[1].Coordinates.X))
            {
                halfEdge = firstHalfEdge;
                edge = firstEdge;
            }
            else
            {
                halfEdge = secondHalfEdge;
                edge = secondEdge;
            }

            isRightOfSite = intersectionPointX >= edge.Region[1].Coordinates.X;

            if ((isRightOfSite && halfEdge.ELpm == LEdge) || (!isRightOfSite && halfEdge.ELpm == REdge))
            {
                return null;
            }

            // create a new site at the point of intersection - this is a new vector; event waiting to happen
            Site intersectionSite = new Site();
            intersectionSite.Coordinates.X = intersectionPointX;
            intersectionSite.Coordinates.Y = intersectionPointY;

            return intersectionSite;
        }
Пример #2
0
        private bool VoronoiBoundaries()
        {
            Site bottom, top, temp, point;
            Site vertex;
            Point newIntersectionStart = null;
            int index;
            HalfEdge leftBoundary, rightBoundary, aboveHalfEdgeLeftBoundary, lowestHalfEdgeRightBoundary, bisector;
            Edge bisectionEdge;

            this.InitPriorityQueue();
            this.InitEdgeList();

            this.bottomSite = this.GoToNextSite();
            Site newSite = this.GoToNextSite();

            while (true)
            {
                if (!this.IsPriorityQueueEmpty())
                {
                    newIntersectionStart = this.ExtractMinPointFromPriorityQueue();
                }

                /// if the lowest site has a smaller y value than the lowest vector intersection, process the site;
                ///otherwise process the vector intersection
                if (newSite != null && (this.IsPriorityQueueEmpty()
                                        || newSite.Coordinates.Y < newIntersectionStart.Y
                                        || (newSite.Coordinates.Y == newIntersectionStart.Y
                                            && newSite.Coordinates.X < newIntersectionStart.X)))
                {
                    /// new site is smallest -this is a site event;
                    /// get the first half edge to the left of the new site
                    leftBoundary = this.FindLeftBoundary(newSite.Coordinates);

                    // get the first HalfEdge to the RIGHT of the new site
                    rightBoundary = this.RightHalfEdge(leftBoundary);

                    // if this halfedge has no edge,bot =bottom site (whatever that
                    // is)
                    bottom = this.GetRightRegion(leftBoundary);

                    // create a new edge that bisects
                    bisectionEdge = this.BisectEdge(bottom, newSite);

                    // create a new HalfEdge, setting its ELpm field to 0
                    bisector = this.CreateHalfEdge(bisectionEdge, LEdge);

                    // insert this new bisector edge between the left and right
                    // vectors in a linked list
                    this.InsertHalfEdge(leftBoundary, bisector);

                    // if the new bisector intersects with the left edge,
                    // remove the left edge's vertex, and put in the new one
                    if ((point = this.Intersect(leftBoundary, bisector)) != null)
                    {
                        this.DeleteHalfEdgeFromPriorityQueue(leftBoundary);
                        double distance = this.CalculateDistance(point, newSite);
                        this.InsertHalfEdgeInPriorityQueue(leftBoundary, point, distance);
                    }

                    leftBoundary = bisector;

                    // create a new HalfEdge, setting its ELpm field to 1
                    bisector = this.CreateHalfEdge(bisectionEdge, REdge);

                    // insert the new HE to the right of the original bisector
                    // earlier in the IF stmt
                    this.InsertHalfEdge(leftBoundary, bisector);

                    // if this new bisector intersects with the new HalfEdge
                    if ((point = this.Intersect(bisector, rightBoundary)) != null)
                    {
                        // push the HE into the ordered linked list of vertices
                        double distance = this.CalculateDistance(point, newSite);
                        this.InsertHalfEdgeInPriorityQueue(bisector, point, distance);
                    }

                    newSite = this.GoToNextSite();
                }
                else if (!this.IsPriorityQueueEmpty())
                {
                    /// intersection is smallest - this is a vector event; pop the HalfEdge with the lowest vector 
                    /// off the ordered list of vectors
                    leftBoundary = this.ExtractMinHalfEdgeFromPriorityQueue();

                    // get the HalfEdge to the left of the above HE
                    aboveHalfEdgeLeftBoundary = this.LeftHalfEdge(leftBoundary);

                    // get the HalfEdge to the right of the above HE
                    rightBoundary = this.RightHalfEdge(leftBoundary);

                    // get the HalfEdge to the right of the HE to the right of the
                    // lowest HE
                    lowestHalfEdgeRightBoundary = this.RightHalfEdge(rightBoundary);

                    // get the Site to the left of the left HE which it bisects
                    bottom = this.GetLeftRegion(leftBoundary);

                    // get the Site to the right of the right HE which it bisects
                    top = this.GetRightRegion(rightBoundary);

                    // get the vertex that caused this event
                    vertex = leftBoundary.Vertex;

                    // set the vertex number
                    this.CreateVertex(vertex);

                    // set the endpoint of the left HalfEdge to be this vector
                    this.SetEndPoint(leftBoundary.Edge, leftBoundary.ELpm, vertex);

                    // set the endpoint of the right HalfEdge to be this vector
                    this.SetEndPoint(rightBoundary.Edge, rightBoundary.ELpm, vertex);

                    // mark the lowest HE for deletion
                    this.DeleteHalfEdge(leftBoundary);

                    // remove all vertex events to do with the right HE
                    this.DeleteHalfEdgeFromPriorityQueue(rightBoundary);

                    // mark the right HE for deletion 
                    this.DeleteHalfEdge(rightBoundary); 
                    index = LEdge; 

                   /// if the site to the left of the event is higher than the site  
                   /// to the right of it, then swap them and set the index variable to 1
                    if (bottom.Coordinates.Y > top.Coordinates.Y)
                    { 
                        temp = bottom;
                        bottom = top;
                        top = temp;
                        index = REdge;
                    }

                    /// create an Edge (or line) that is between the two Sites. This creates the formula of
                    /// the line, and assigns a line number to it
                    bisectionEdge = this.BisectEdge(bottom, top);

                    // create a HE from the edge and make it point to that edge with its ELedge field
                    bisector = this.CreateHalfEdge(bisectionEdge, index); 

                    // insert the new bisector to the right of the left HE
                    this.InsertHalfEdge(aboveHalfEdgeLeftBoundary, bisector);

                    /// Set one endpoint to the new edge to be the vector point 'v'; If the site to the left of this 
                    /// bisector is higher than the right site, then this endpoint is put in position 0; 
                    /// otherwise - in position 1
                    this.SetEndPoint(bisectionEdge, REdge - index, vertex); 

                    /// if left half edge and the new bisector intersect, then delete
                    /// the left half edge, and reinsert it
                    if ((point = this.Intersect(aboveHalfEdgeLeftBoundary, bisector)) != null)
                    {
                        double distance = this.CalculateDistance(point, bottom);
                        this.DeleteHalfEdgeFromPriorityQueue(aboveHalfEdgeLeftBoundary);
                        this.InsertHalfEdgeInPriorityQueue(aboveHalfEdgeLeftBoundary, point, distance);
                    }

                    // if right half edge and the new bisector intersect, then reinsert it
                    if ((point = this.Intersect(bisector, lowestHalfEdgeRightBoundary)) != null)
                    {
                        double distance = this.CalculateDistance(point, bottom);
                        this.InsertHalfEdgeInPriorityQueue(bisector, point, distance);
                    }
                }
                else
                {
                    break;
                }
            }

            for (leftBoundary = this.RightHalfEdge(this.edgeListLeftEnd); leftBoundary != this.edgeListRightEnd; leftBoundary = this.RightHalfEdge(leftBoundary))
            {
                bisectionEdge = leftBoundary.Edge;
                this.ClipLine(bisectionEdge);
            }

            return true;
        }
Пример #3
0
        private void SetEndPoint(Edge edge, int index, Site site)
        {
            edge.EdgePoints[index] = site;

            if (edge.EdgePoints[REdge - index] == null)
            {
                return;
            }

            this.ClipLine(edge);
        }
Пример #4
0
 private double CalculateDistance(Site firstSite, Site secondSite)
 {
     double dX = firstSite.Coordinates.X - secondSite.Coordinates.X;
     double dY = firstSite.Coordinates.Y - secondSite.Coordinates.Y;
     return Math.Sqrt((dX * dX) + (dY * dY));
 }
Пример #5
0
        private void PushGraphEdge(Site leftSite, Site rightSite, double x1, double y1, double x2, double y2)
        {
            GraphEdge newEdge = new GraphEdge();
            this.graphEdgesList.Add(newEdge);
            newEdge.X1 = x1;
            newEdge.Y1 = y1;
            newEdge.X2 = x2;
            newEdge.Y2 = y2;

            newEdge.FirstSiteIndex = leftSite.SiteIndex;
            newEdge.SecondSiteIndex = rightSite.SiteIndex;
        }
Пример #6
0
        // push the HalfEdge into the ordered linked list of vertices
        private void InsertHalfEdgeInPriorityQueue(HalfEdge halfEdge, Site site, double offset)
        {
            HalfEdge nextHalfEdge;

            halfEdge.Vertex = site;
            halfEdge.YStart = (double)(site.Coordinates.Y + offset);
            HalfEdge lastHalfEdge = this.priorityQueueHash[this.GetPriorityQueueBucket(halfEdge)];

            while ((nextHalfEdge = lastHalfEdge.NextPriorityQueueMember) != null &&
                  (halfEdge.YStart > nextHalfEdge.YStart || 
                  (halfEdge.YStart == nextHalfEdge.YStart && 
                   site.Coordinates.X > nextHalfEdge.Vertex.Coordinates.X)))
            {
                lastHalfEdge = nextHalfEdge;
            }

            halfEdge.NextPriorityQueueMember = lastHalfEdge.NextPriorityQueueMember;
            lastHalfEdge.NextPriorityQueueMember = halfEdge;
            this.priorityQueueMembersCount++;
        }
Пример #7
0
 private void CreateVertex(Site vertex)
 {
     vertex.SiteIndex = this.verticesCount;
     this.verticesCount++;
 }
Пример #8
0
        private Edge BisectEdge(Site firstSite, Site secondSite)
        {
            double dX = 0.0d;
            double dY = 0.0d;
            double adX = 0.0d;
            double adY = 0.0d;

            Edge newEdge = new Edge();

            newEdge.Region[0] = firstSite;
            newEdge.Region[1] = secondSite;

            newEdge.EdgePoints[0] = null;
            newEdge.EdgePoints[1] = null;

            dX = secondSite.Coordinates.X - firstSite.Coordinates.X;
            dY = secondSite.Coordinates.Y - firstSite.Coordinates.Y;

            adX = dX > 0 ? dX : -dX;
            adY = dY > 0 ? dY : -dY;

            newEdge.C = (double)((firstSite.Coordinates.X * dX) + (firstSite.Coordinates.Y * dY) + (((dX * dX) + (dY * dY)) * 0.5));

            if (adX > adY)
            {
                newEdge.A = 1.0;
                newEdge.B = dY / dX;
                newEdge.C /= dX;
            }
            else
            {
                newEdge.A = dX / dY;
                newEdge.B = 1.0;
                newEdge.C /= dY;
            }

            newEdge.EdgeN = this.edgesCount;
            this.edgesCount++;

            return newEdge;
        }
Пример #9
0
        private void SortSites(Site[] sites)
        {
            List<Site> sitesList = new List<Site>(sites.Length);

            for (int i = 0; i < sites.Length; i++)
            {
                sitesList.Add(sites[i]);
            }

            sitesList.Sort(new SiteSorter());

            // Copy back into the array
            for (int i = 0; i < sites.Length; i++)
            {
                sites[i] = sitesList[i];
            }
        }