Пример #1
0
        public EdgeList( SiteList siteList) {
            Edges = new List<HalfEdge>();
            _siteList = siteList;
            LeftEnd = new HalfEdge(null, Side.Left);
            RightEnd = new HalfEdge(null, Side.Left);
            LeftEnd.Right = RightEnd;
            RightEnd.Left = LeftEnd;

            Edges.Add(LeftEnd);
            Edges.Add(RightEnd);
        }
Пример #2
0
 public void Insert(HalfEdge he, Site site, float offset) {
     he.Vertex = site;
     he.YStar = site.Y + offset;
     int i;
     for (i = 0; i < _events.Count; i++) {
         var next = _events[i];
         if (he.YStar > next.YStar || (Math.Abs(he.YStar - next.YStar) < Geometry.Tolerance && site.X > next.Vertex.X)) {
             continue;
         }
         break;
     }
     _events.Insert(i, he);
 }
Пример #3
0
        public static bool RightOf(HalfEdge he, Site p) {
            var e = he.Edge;
            var topSite = e.Region[Side.Right];
            var rightOfSite = (p.X > topSite.X);

            if (rightOfSite && (he.Side == Side.Left)) {
                return true;
            }
            if (!rightOfSite && (he.Side == Side.Right)) {
                return false;
            }
            bool above;
            if (Math.Abs(e.A - 1) < Tolerance) {
                var dyp = p.Y - topSite.Y;
                var dxp = p.X - topSite.X;
                var fast = false;
                

                if ((!rightOfSite && (e.B < 0)) || (rightOfSite && (e.B >= 0))) {
                    above = fast = (dyp >= e.B*dxp);
                } else {
                    above = ((p.X + p.Y*e.B) > e.C);
                    if (e.B < 0) {
                        above = !above;
                    }
                    if (!above) {
                        fast = true;
                    }
                }
                if (!fast) {
                    var dxs = topSite.X - e.Region[Side.Left].X;
                    above = (e.B*(dxp*dxp - dyp*dyp)) < (dxs*dyp*(1 + 2*dxp/dxs + e.B*e.B));

                    if (e.B < 0) {
                        above = !above;
                    }
                }
            } else { // e.b == 1
                var y1 = e.C - e.A*p.X;
                var t1 = p.Y - y1;
                var t2 = p.X - topSite.X;
                var t3 = y1 - topSite.Y;

                above = (t1*t1) > (t2*t2 + t3*t3);
            }
            return he.Side == Side.Left ? above : !above;
        }
Пример #4
0
        public static Site Intersect(HalfEdge el1, HalfEdge el2) {
            var e1 = el1.Edge;
            var e2 = el2.Edge;
            if (e1 == null || e2 == null) {
                return null;
            }
            if (e1.Region[Side.Right] == e2.Region[Side.Right]) {
                return null;
            }
            var d = (e1.A*e2.B) - (e1.B*e2.A);
            if (Math.Abs(d) < Tolerance) {
                return null;
            }
            var xint = (e1.C*e2.B - e2.C*e1.B)/d;
            var yint = (e2.C*e1.A - e1.C*e2.A)/d;

            var e1Region = e1.Region[Side.Right];
            var e2Region = e2.Region[Side.Right];

            HalfEdge el;
            Edge e;
            if ((e1Region.Y < e2Region.Y) || Math.Abs(e1Region.Y - e2Region.Y) < Tolerance && e1Region.X < e2Region.X) {
                el = el1;
                e = e1;
            } else {
                el = el2;
                e = e2;
            }
            var rightOfSite = (xint >= e.Region[Side.Right].X);
            if ((rightOfSite && (el.Side == Side.Left)) || (!rightOfSite && (el.Side == Side.Right))) {
                return null;
            }

            var vertex = new Site(xint, yint);
            //vertex.AddEdge(e1);
            //vertex.AddEdge(e2);
            return vertex;
        }
Пример #5
0
        public VoronoiGraph StepVoronoi() {
            _graph.ResetNewItems();
            if (!_edgeFixup) {
                if (!_eventQueue.IsEmpty) {
                    _newIntStar = _eventQueue.Min();
                    
                }

                if (_newSite != null && (_eventQueue.IsEmpty || /*Geometry.CompareByYThenX(_newSite, _newIntStar)*/ _newSite.CompareTo(_newIntStar) < 0 )) {

                    _graph.PlotSite(_newSite);

                    var lbnd = _edgeList.LeftBound(_newSite);
                    var rbnd = lbnd.Right;
                    var bot = _edgeList.RightRegion(lbnd);
                    var e = Edge.CreateBisectingEdge(bot, _newSite);
                    _graph.PlotBisector(e);
                    var bisector = new HalfEdge(e, Side.Left);
                    EdgeList.Insert(lbnd, bisector);
                    var p = Site.CreateIntersectingSite(lbnd, bisector);
                    if (p != null) {
                        _eventQueue.Delete(lbnd);
                        if (_graph.Debug) {
                            Console.WriteLine("Inserting {0}", p);
                        }
                        _eventQueue.Insert(lbnd, p, Site.Distance(p, _newSite));
                    }
                    lbnd = bisector;
                    bisector = new HalfEdge(e, Side.Right);
                    EdgeList.Insert(lbnd, bisector);
                    p = Site.CreateIntersectingSite(bisector, rbnd);
                    if (p != null) {
                        if (_graph.Debug) {
                            Console.WriteLine("Inserting {0}", p);
                        }
                        _eventQueue.Insert(bisector, p, Site.Distance(p, _newSite));
                    }
                    _newSite = _sites.ExtractMin();
                    if (_newSite !=null && _newSite.Y > _graph.SweepLine) {
                        _graph.SweepLine = _newSite.Y;
                    } else if (_newSite == null) {
                        _graph.SweepLine = _graph.Height;
                    }

                } else if (!_eventQueue.IsEmpty) { // intersection is smallest
                    var lbnd = _eventQueue.ExtractMin();
                    var llbnd = lbnd.Left;
                    var rbnd = lbnd.Right;
                    var rrbnd = rbnd.Right;
                    var bot = _edgeList.LeftRegion(lbnd);
                    var top = _edgeList.RightRegion(rbnd);
                    _graph.PlotTriple(bot, top, _edgeList.RightRegion(lbnd));
                    var v = lbnd.Vertex;

                    _graph.PlotVertex(v);

                    _graph.EndPoint(lbnd.Edge, lbnd.Side, v);
                    _graph.EndPoint(rbnd.Edge, rbnd.Side, v);
                    EdgeList.Delete(lbnd);
                    _eventQueue.Delete(rbnd);
                    EdgeList.Delete(rbnd);
                    var pm = Side.Left;
                    if (bot.Y > top.Y) {
                        var temp = bot;
                        bot = top;
                        top = temp;
                        pm = Side.Right;
                    }
                    var e = Edge.CreateBisectingEdge(bot, top);
                    _graph.PlotBisector(e);
                    var bisector = new HalfEdge(e, pm);
                    EdgeList.Insert(llbnd, bisector);
                    _graph.EndPoint(e, pm == Side.Left ? Side.Right : Side.Left, v);
                    var p = Site.CreateIntersectingSite(llbnd, bisector);
                    if (p != null) {
                        _eventQueue.Delete(llbnd);
                        if (_graph.Debug) {
                            Console.WriteLine("Inserting {0}", p);
                        }
                        _eventQueue.Insert(llbnd, p, Site.Distance(p, bot));
                    }
                    p = Site.CreateIntersectingSite(bisector, rrbnd);
                    if (p != null) {
                        if (_graph.Debug) {
                            Console.WriteLine("Inserting {0}", p);
                        }
                        _eventQueue.Insert(bisector, p, Site.Distance(p, bot));
                    }
                } else {
                    _edgeFixup = true;
                }
                StepNumber++;
            } else {
                var lbnd = _edgeList.LeftEnd.Right;
                if (lbnd != _edgeList.RightEnd) {
                    var e = lbnd.Edge;
                    _graph.PlotEndpoint(e);
                    EdgeList.Delete(lbnd);
                    StepNumber++;
                } else {
                    foreach (var edge in _graph.Edges) {
                        edge.ClipVertices(new Rectangle(0, 0, _graph.Width, _graph.Height));
                    }
                    if (_graph.Debug) {
                        Console.WriteLine("Done computing graph!");
                    }
                }
            }
            if (_graph.Debug) {
                Console.WriteLine("Step: " + StepNumber);
            }
            return _graph;
        }
Пример #6
0
        public static VoronoiGraph ComputeVoronoi(IEnumerable<PointF> points, int w = 800, int h = 600, bool debug=false) {
            var sites = new SiteList(points);
            sites.LogSites();
            var graph = new VoronoiGraph(w, h) { Debug = debug };
            try {
                var edgeList = new EdgeList(sites);
                var eventQueue = new EventQueue();

                sites.BottomSite = sites.ExtractMin();

                graph.PlotSite(sites.BottomSite);

                var newSite = sites.ExtractMin();
                var newIntStar = new Site(float.MaxValue, float.MaxValue);

                while (true) {
                    if (!eventQueue.IsEmpty) {
                        newIntStar = eventQueue.Min();
                    }
                    // new site is smallest
                    if (newSite != null && 
                        (eventQueue.IsEmpty || newSite.Y < newIntStar.Y || (Math.Abs(newSite.Y - newIntStar.Y) < Geometry.Tolerance && newSite.X < newIntStar.X))) {

                        graph.PlotSite(newSite);

                        var lbnd = edgeList.LeftBound(newSite);
                        var rbnd = lbnd.Right;
                        var bot = edgeList.RightRegion(lbnd);
                        var e = Geometry.Bisect(bot, newSite);
                        graph.PlotBisector(e);
                        var bisector = new HalfEdge(e, Side.Left);
                        edgeList.Insert(lbnd, bisector);
                        var p = Geometry.Intersect(lbnd, bisector);
                        if (p != null) {
                            eventQueue.Delete(lbnd);
                            if (debug) {
                                Console.WriteLine("Inserting {0}", p);
                            }
                            eventQueue.Insert(lbnd, p, Geometry.Distance(p, newSite));
                        }
                        lbnd = bisector;
                        bisector = new HalfEdge(e, Side.Right);
                        edgeList.Insert(lbnd, bisector);
                        p = Geometry.Intersect(bisector, rbnd);
                        if (p != null) {
                            if (debug) {
                                Console.WriteLine("Inserting {0}", p);
                            }
                            eventQueue.Insert(bisector, p, Geometry.Distance(p, newSite));
                        }
                        newSite = sites.ExtractMin();
                    } else if (!eventQueue.IsEmpty) { // intersection is smallest
                        var lbnd = eventQueue.ExtractMin();
                        var llbnd = lbnd.Left;
                        var rbnd = lbnd.Right;
                        var rrbnd = rbnd.Right;
                        var bot = edgeList.LeftRegion(lbnd);
                        var top = edgeList.RightRegion(rbnd);
                        graph.PlotTriple(bot, top, edgeList.RightRegion(lbnd));
                        var v = lbnd.Vertex;

                        graph.PlotVertex(v);



                        Geometry.EndPoint(lbnd.Edge, lbnd.Side, v, graph);
                        Geometry.EndPoint(rbnd.Edge, rbnd.Side, v, graph);
                        edgeList.Delete(lbnd);
                        eventQueue.Delete(rbnd);
                        edgeList.Delete(rbnd);
                        var pm = Side.Left;
                        if (bot.Y > top.Y) {
                            var temp = bot;
                            bot = top;
                            top = temp;
                            pm = Side.Right;
                        }
                        var e = Geometry.Bisect(bot, top);
                        graph.PlotBisector(e);
                        var bisector = new HalfEdge(e, pm);
                        edgeList.Insert(llbnd, bisector);
                        Geometry.EndPoint(e, Side.Other(pm), v, graph);
                        var p = Geometry.Intersect(llbnd, bisector);
                        if (p != null) {
                            eventQueue.Delete(llbnd);
                            if (debug) {
                                Console.WriteLine("Inserting {0}", p);
                            }
                            eventQueue.Insert(llbnd, p, Geometry.Distance(p, bot));
                        }
                        p = Geometry.Intersect(bisector, rrbnd);
                        if (p != null) {
                            if (debug) {
                                Console.WriteLine("Inserting {0}", p);
                            }
                            eventQueue.Insert(bisector, p, Geometry.Distance(p, bot));
                        }
                    } else {
                        break;
                    }
                }
                for (var lbnd = edgeList.LeftEnd.Right; lbnd != edgeList.RightEnd; lbnd = lbnd.Right) {
                    var e = lbnd.Edge;
                    graph.PlotEndpoint(e);
                }
            } catch (Exception ex) {
                Console.WriteLine("########################################");
                Console.WriteLine(ex.Message);
                Console.WriteLine(ex.StackTrace);
            }
            graph.SweepLine = graph.Height;
            graph.ResetNewItems();
            foreach (var edge in graph.Edges) {
                edge.ClipVertices(new Rectangle(0,0, w, h));
            }
            
            return graph;
        }
Пример #7
0
 public void Delete(HalfEdge he)
 {
     _events.Remove(he);
 }
Пример #8
0
 public Site RightRegion(HalfEdge he) {
     if (he.Edge == null) {
         return _siteList.BottomSite;
     }
     return he.Side == Side.Left ? he.Edge.Region[Side.Right] : he.Edge.Region[Side.Left];
 }
Пример #9
0
 public void Delete(HalfEdge he) {
     he.Left.Right = he.Right;
     he.Right.Left = he.Left;
     he.Edge = null;
 }
Пример #10
0
 public void Insert(HalfEdge lb, HalfEdge he) {
     he.Left = lb;
     he.Right = lb.Right;
     lb.Right.Left = he;
     lb.Right = he;
 }
Пример #11
0
 public void Delete(HalfEdge he) {
     _events.Remove(he);
 }