Exemple #1
0
        public void Compute(HashSet<Point> points, int width, int height)
        {
            _root = null;
            _width = width;
            _height = height;

            if (points.Count < 2)
            {
                return;
            }

            Edges = new List<Edge>();
            Cells = new List<Cell>();
            _queue = new Queue();

            foreach (Point point in points)
            {
                var @event = new Event(point, true);
                var cell = new Cell(point);
                point.Cell = cell;
                _queue.Enqueue(@event);
                Cells.Add(cell);
            }

            while (!_queue.IsEmpty())
            {
                Event @event = _queue.Dequeue();
                _ly = @event.Point.Y;

                if (@event.IsParabola)
                {
                    InsertParabola(@event.Point);
                }
                else
                {
                    RemoveParabola(@event);
                }

                _lasty = @event.Point.Y;
            }

            FinishEdge(_root);

            for (var i = 0; i < Edges.Count; i++)
            {
                if (Edges[i].Neighbour != null)
                {
                    Edges[i].Start = Edges[i].Neighbour.End;
                }
            }
        }
Exemple #2
0
        private void CheckCircle(Parabola b)
        {
            Parabola lp = GetLeftParent(b);
            Parabola rp = GetRightParent(b);

            Parabola a = GetLeftChild(lp);
            Parabola c = GetRightChild(rp);

            if (a == null || c == null || Equals(a.Site, c.Site)) return;

            Point s = GetEdgeIntersection(lp.Edge, rp.Edge);
            if (s == null) return;

            double d = Distance(a.Site, s);

            if (s.Y - d >= _ly) return;

            var e = new Event(new Point(s.X, s.Y - d), false);

            b.CircleEvent = e;
            e.Arch = b;
            _queue.Enqueue(e);
        }
Exemple #3
0
        private void InsertParabola(Point p)
        {
            if (_root == null)
            {
                _root = new Parabola(p);
                _fp = p;
                return;
            }

            if (_root.IsLeaf && _root.Site.Y - p.Y < 0.01)
            {
                _root.IsLeaf = false;
                _root.Left = new Parabola(_fp);
                _root.Right = new Parabola(p);

                var s = new Point((p.X + _fp.X)/2, _height);
                if (p.X > _fp.X)
                {
                    _root.Edge = new Edge(s, _fp, p);
                }
                else
                {
                    _root.Edge = new Edge(s, p, _fp);
                }

                Edges.Add(_root.Edge);
                return;
            }

            Parabola par = GetParabolaByX(p.X);

            if (par.CircleEvent != null)
            {
                _queue.Remove(par.CircleEvent);
                par.CircleEvent = null;
            }

            var start = new Point(p.X, GetY(par.Site, p.X));

            var el = new Edge(start, par.Site, p);
            var er = new Edge(start, p, par.Site);

            el.Neighbour = er;
            Edges.Add(el);

            par.Edge = er;
            par.IsLeaf = false;

            var p0 = new Parabola(par.Site);
            var p1 = new Parabola(p);
            var p2 = new Parabola(par.Site);

            par.Right = p2;
            par.Left = new Parabola();

            par.Left.Edge = el;
            par.Left.Left = p0;
            par.Left.Right = p1;

            CheckCircle(p0);
            CheckCircle(p2);
        }
Exemple #4
0
        private double GetXOfEdge(Parabola par, double y)
        {
            Parabola left = GetLeftChild(par);
            Parabola right = GetRightChild(par);

            Point p = left.Site;
            Point r = right.Site;

            double dp = 2*(p.Y - y);
            double a1 = 1/dp;
            double b1 = -2*p.X/dp;
            double c1 = y + dp*0.25 + p.X*p.X/dp;

            dp = 2*(r.Y - y);
            double a2 = 1/dp;
            double b2 = -2*r.X/dp;
            double c2 = y + dp*0.25 + r.X*r.X/dp;

            double a = a1 - a2;
            double b = b1 - b2;
            double c = c1 - c2;

            double disc = b*b - 4*a*c;
            double x1 = (-b + Math.Sqrt(disc))/(2*a);
            double x2 = (-b - Math.Sqrt(disc))/(2*a);

            double ry;
            if (p.Y < r.Y) ry = Math.Max(x1, x2);
            else ry = Math.Min(x1, x2);

            return ry;
        }
Exemple #5
0
 private Parabola GetRightParent(Parabola n)
 {
     Parabola par = n.Parent;
     Parabola pLast = n;
     while (par.Right == pLast)
     {
         if (par.Parent == null) return null;
         pLast = par;
         par = par.Parent;
     }
     return par;
 }
Exemple #6
0
        private Parabola GetRightChild(Parabola n)
        {
            if (n == null) return null;

            Parabola par = n.Right;
            while (!par.IsLeaf) par = par.Left;
            return par;
        }
Exemple #7
0
        private void FinishEdge(Parabola n)
        {
            double mx;
            if (n.Edge.Direction.X > 0.0f)
            {
                mx = Math.Max(_width, n.Edge.Start.X + 10);
            }
            else
            {
                mx = Math.Min(0.0f, n.Edge.Start.X - 10);
            }
            n.Edge.End = new Point(mx, n.Edge.F * mx + n.Edge.G);

            if (!n.Left.IsLeaf) this.FinishEdge(n.Left);
            if (!n.Right.IsLeaf) this.FinishEdge(n.Right);
        }