void FinishEdge(BeachNode node)
    {
        if (node.GetType() == typeof(BeachArc))
        {
            return;
        }
        BeachEdge n = (BeachEdge)node;
        float     mx;

        if (n.edge.direction.x > 0)
        {
            mx = Mathf.Max(width, n.edge.start.pos.x + 10);
        }
        else
        {
            mx = Mathf.Max(0, n.edge.start.pos.x - 10);
        }

        Vertex end = new Vertex(new Vector2(mx, mx * n.edge.f + n.edge.g));

        n.edge.end = end;
        diagram.vertices.Add(end);
        diagram.edges.Add(n.edge);

        FinishEdge(n.left);
        FinishEdge(n.right);
    }
    public void CheckCircle(BeachArc mid)
    {
        BeachEdge leftParent  = BeachNode.GetLeftParent(mid);
        BeachEdge rightParent = BeachNode.GetRightParent(mid);

        BeachArc left  = BeachNode.GetLeftChild(leftParent);
        BeachArc right = BeachNode.GetRightChild(rightParent);

        if (left == null || right == null || left.site == right.site)
        {
            return;
        }

        Vector2 s = GetEdgeIntersection(leftParent.edge, rightParent.edge);

        if (float.IsNaN(s.x) || float.IsNaN(s.y))
        {
            return;
        }

        float dx = left.site.pos.x - s.x;
        float dy = left.site.pos.y - s.y;

        float d = Mathf.Sqrt((dx * dx) + (dy * dy));

        if (s.y - d >= sweep)
        {
            return;
        }

        VertexEvent ev = new VertexEvent(left, mid, right);

        mid.ev = ev;
        events.Add(ev);
    }
    public float GetXOfEdge(BeachEdge n, float y)
    {
        BeachArc left  = BeachNode.GetLeftChild(n);
        BeachArc right = BeachNode.GetRightChild(n);

        Vector2 p = left.site.pos;
        Vector2 r = right.site.pos;

        float dp = 2f * (p.y - y);
        float a1 = 1f / dp;
        float b1 = -2f * p.x / dp;
        float c1 = y + dp / 4 + p.x * p.x / dp;

        dp = 2f * (r.y - y);
        float a2 = 1f / dp;
        float b2 = -2f * r.x / dp;
        float c2 = sweep + dp / 4 + r.x * r.x / dp;

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

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

        float xl = Mathf.Min(x1, x2);
        float xr = Mathf.Max(x1, x2);


        float ry;

        if (p.y < r.y)
        {
            ry = Mathf.Max(x1, x2);
        }
        else
        {
            ry = Mathf.Min(x1, x2);
        }
        return(ry);

        /*
         * if(p.x < r.x) //going L to R
         * {
         *  if (r.y < p.y)
         *      return xl;
         *  else
         *      return xr;
         * }
         * else
         * {
         *  if (p.y < r.y)
         *      return xr;
         *  else
         *      return xl;
         * }*/
    }
 string PrintNode(BeachNode n)
 {
     if (n.GetType() == typeof(BeachArc))
     {
         return(((BeachArc)n).site.name + " ");
     }
     else
     {
         BeachEdge edgeNode = (BeachEdge)n;
         string    left     = PrintNode(n.left);
         string    right    = PrintNode(n.right);
         float     x        = GetXOfEdge(edgeNode, sweep);
         float     y        = edgeNode.edge.f * x + edgeNode.edge.g;
         return(left + "[" + x.ToString("0.0") + ", " + y.ToString("0.0") + "] " + right);
     }
 }
    List <Vector2> GetBreaks(BeachNode n)
    {
        if (n.GetType() == typeof(BeachArc))
        {
            return(new List <Vector2>());
        }
        BeachEdge      edgeNode = (BeachEdge)n;
        List <Vector2> left     = GetBreaks(n.left);
        float          x        = GetXOfEdge(edgeNode, sweep);
        float          y        = edgeNode.edge.f * x + edgeNode.edge.g;

        left.Add(new Vector2(x, y));
        List <Vector2> right = GetBreaks(n.right);

        left.AddRange(right);
        return(left);
    }
    public void Insert(Cell c)
    {
        Vertex start;
        Edge   edge;

        if (root == null)
        {
            root = new BeachArc(c);
            return;
        }
        if (root.GetType() == typeof(BeachArc) && ((BeachArc)root).site.pos.y - c.pos.y < 1)
        {
            BeachArc temp = (BeachArc)root;
            root = new BeachEdge();
            if (c.pos.x < temp.site.pos.x)
            {
                root.left  = new BeachArc(c);
                root.right = temp;
            }
            else
            {
                root.left  = temp;
                root.right = new BeachArc(c);
            }
            start = new Vertex(new Vector2(c.pos.x, GetY(temp.site.pos, c.pos.x)));
            diagram.vertices.Add(start);
            if (c.pos.x > temp.site.pos.x)
            {
                edge = new Edge(start, temp.site, c);
                ((BeachEdge)root).edge = edge;
            }
            else
            {
                edge = new Edge(start, c, temp.site);
                ((BeachEdge)root).edge = edge;
            }
            diagram.edges.Add(edge);
            return;
        }

        BeachArc par = GetParabolaByX(c.pos.x);

        if (par.ev != null) //If hit arc is the center of a triplet, remove it
        {
            events.Remove(par.ev);
            par.ev = null;
        }

        start = new Vertex(new Vector2(c.pos.x, GetY(par.site.pos, c.pos.x)));
        diagram.vertices.Add(start);

        Edge left  = new Edge(start, par.site, c);
        Edge right = new Edge(start, c, par.site);

        left.section = right;
        diagram.edges.Add(left);

        BeachArc p0 = new BeachArc(par.site);
        BeachArc p1 = new BeachArc(c);
        BeachArc p2 = new BeachArc(par.site);

        BeachEdge subroot = new BeachEdge();

        subroot.edge = right;
        if (par == par.parent.left)
        {
            par.parent.left = subroot;
        }
        else
        {
            par.parent.right = subroot;
        }

        subroot.right      = p2;
        subroot.left       = new BeachEdge(left);
        subroot.left.left  = p0;
        subroot.left.right = p1;

        CheckCircle(p0);
        CheckCircle(p2);
    }
    public void Remove(VertexEvent e)
    {
        BeachArc mid = e.arcs[1];

        BeachEdge leftEdge  = BeachNode.GetLeftParent(mid);
        BeachEdge rightEdge = BeachNode.GetRightParent(mid);

        BeachArc left  = BeachNode.GetLeftChild(leftEdge);
        BeachArc right = BeachNode.GetRightChild(rightEdge);

        if (left.ev != null)
        {
            events.Remove(left.ev);
            left.ev = null;
        }
        if (right.ev != null)
        {
            events.Remove(right.ev);
            right.ev = null;
        }

        Vertex end = new Vertex(e.center);

        diagram.vertices.Add(end);
        leftEdge.edge.end  = end;
        rightEdge.edge.end = end;

        diagram.edges.Add(leftEdge.edge);
        diagram.edges.Add(rightEdge.edge);

        BeachEdge higher = null;
        BeachNode par    = mid;

        while (par != root)
        {
            par = par.parent;
            if (par == leftEdge)
            {
                higher = leftEdge;
            }
            if (par == rightEdge)
            {
                higher = rightEdge;
            }
        }
        higher.edge = new Edge(end, left.site, right.site);
        diagram.edges.Add(higher.edge);

        BeachEdge gparent = (BeachEdge)mid.parent.parent;

        if (mid.parent.left == mid)
        {
            if (gparent.left == mid.parent)
            {
                gparent.left = mid.parent.right;
            }
            if (gparent.right == mid.parent)
            {
                gparent.right = mid.parent.right;
            }
        }
        else
        {
            if (gparent.left == mid.parent)
            {
                gparent.left = mid.parent.left;
            }
            if (gparent.right == mid.parent)
            {
                gparent.right = mid.parent.left;
            }
        }

        CheckCircle(left);
        CheckCircle(right);
    }