
/*** VORONOI.C ***/

#include "vdefs.h"

extern Site * bottomsite ;
extern Halfedge * ELleftend, * ELrightend ;

/*** implicit parameters: nsites, sqrt_nsites, xmin, xmax, ymin, ymax,
 : deltax, deltay (can all be estimates).
 : Performance suffers if they are wrong; better to make nsites,
 : deltax, and deltay too big than too small.  (?)
 ***/

void
voronoi(Site *(*nextsite)(void))
    {
    Site * newsite, * bot, * top, * temp, * p, * v ;
    Point newintstar ;
    int pm ;
    Halfedge * lbnd, * rbnd, * llbnd, * rrbnd, * bisector ;
    Edge * e ;

    PQinitialize() ;
    bottomsite = (*nextsite)() ;
    out_site(bottomsite) ;
    ELinitialize() ;
    newsite = (*nextsite)() ;
    newintstar.x = 0; /* gcc -Wall */
    newintstar.y = 0; /* gcc -Wall */
    while (1)
        {
        if(!PQempty())
            {
            newintstar = PQ_min() ;
            }
        if (newsite != (Site *)NULL && (PQempty()
            || newsite -> coord.y < newintstar.y
            || (newsite->coord.y == newintstar.y
            && newsite->coord.x < newintstar.x)))
            {/* new site is smallest */
            out_site(newsite) ;
            lbnd = ELleftbnd(&(newsite->coord)) ;
            rbnd = ELright(lbnd) ;
            bot = rightreg(lbnd) ;
            e = bisect(bot, newsite) ;
            bisector = HEcreate(e, le) ;
            ELinsert(lbnd, bisector) ;
            p = intersect(lbnd, bisector) ;
            if (p != (Site *)NULL)
                {
                PQdelete(lbnd) ;
                PQinsert(lbnd, p, dist(p,newsite)) ;
                }
            lbnd = bisector ;
            bisector = HEcreate(e, re) ;
            ELinsert(lbnd, bisector) ;
            p = intersect(bisector, rbnd) ;
            if (p != (Site *)NULL)
                {
                PQinsert(bisector, p, dist(p,newsite)) ;
                }
            newsite = (*nextsite)() ;
            }
        else if (!PQempty())   /* intersection is smallest */
            {
            lbnd = PQextractmin() ;
            llbnd = ELleft(lbnd) ;
            rbnd = ELright(lbnd) ;
            rrbnd = ELright(rbnd) ;
            bot = leftreg(lbnd) ;
            top = rightreg(rbnd) ;
            out_triple(bot, top, rightreg(lbnd)) ;
            v = lbnd->vertex ;
            makevertex(v) ;
            endpoint(lbnd->ELedge, lbnd->ELpm, v);
            endpoint(rbnd->ELedge, rbnd->ELpm, v) ;
            ELdelete(lbnd) ;
            PQdelete(rbnd) ;
            ELdelete(rbnd) ;
            pm = le ;
            if (bot->coord.y > top->coord.y)
                {
                temp = bot ;
                bot = top ;
                top = temp ;
                pm = re ;
                }
            e = bisect(bot, top) ;
            bisector = HEcreate(e, pm) ;
            ELinsert(llbnd, bisector) ;
            endpoint(e, re-pm, v) ;
            deref(v) ;
            p = intersect(llbnd, bisector) ;
            if (p  != (Site *) NULL)
                {
                PQdelete(llbnd) ;
                PQinsert(llbnd, p, dist(p,bot)) ;
                }
            p = intersect(bisector, rrbnd) ;
            if (p != (Site *) NULL)
                {
                PQinsert(bisector, p, dist(p,bot)) ;
                }
            }
        else
            {
            break ;
            }
        }

    for( lbnd = ELright(ELleftend) ;
         lbnd != ELrightend ;
         lbnd = ELright(lbnd))
        {
        e = lbnd->ELedge ;
        out_ep(e) ;
        }
    }

