#include <stdio.h>
#include <stdlib.h>
#include "data.h"
int finished=0;
float xmin, xmax, ymin, ymax;
int nsites, ndtedges, ntriples, sqrt_nsites, siteidx;
Freelist wavefront_fl;
Site *sites;
int *main_ac;
char **main_av;
float sweep_line;
VarArray dtedge_va, triple_va, rectangle_va;
int b_debug;
extern int screen_number;
int main(int ac, char **av)
{
int i;
char c;
int *t;
main_ac = ∾ main_av = av;
x_init();
x_parse_options();
x_openwin();
t = &screen_number;
while ((c = getopt(ac, av, "d")) != EOF) {
switch(c) {
case 'd':
b_debug = 1 ;
break ;
}
}
if (ac>1) nsites = atoi(av[1]);
sites = myalloc(nsites * sizeof (Site));
siteidx = 0;
gen_sites (sites, nsites);
warn("the original sites\n");
dump_sites();
qsort(sites, nsites, sizeof(Site), scomp) ;
warn("the sorted sites\n");
dump_sites();
ymin = sites[0].coord[Y];
ymin = sites[0].coord[Y];
for (i=0; i<nsites; i++) {
if (sites[i].coord[Y] < ymin) ymin = sites[i].coord[Y];
if (sites[i].coord[Y] > ymax) ymax = sites[i].coord[Y];
}
geominit();
memoryinit();
EQinit();
WFinit();
x_mainloop();
return 0;
}
void gen_sites(Site *base, int n)
{
FILE *randdev;
struct timeval tv;
int i;
warn("[%s] generating %d sites\n", __func__, nsites);
if ((randdev = fopen("/dev/random","r")) == NULL) {
gettimeofday(&tv, NULL);
i = tv.tv_usec;
} else i = getc(randdev);
srand(10);
for (i=0; i<n; i++) {
#ifdef RANDFLOAT
sites[i].coord[X] = 1.0 + WIDTH *(rand()/(RAND_MAX+1.0));
sites[i].coord[Y] = 1.0 + HEIGHT*(rand()/(RAND_MAX+1.0));
#else
sites[i].coord[X] = 1 + (int)((float)WIDTH *rand()/(RAND_MAX+1.0));
sites[i].coord[Y] = 1 + (int)((float)HEIGHT*rand()/(RAND_MAX+1.0));
#endif
sites[i].sitenbr = i;
}
}
int scomp(const void *vs1, const void *vs2)
{
Site *s1 = (Site *)vs1 ;
Site *s2 = (Site *)vs2 ;
if (s1->coord[X] < s2->coord[X]) return -1;
else if (s1->coord[X] > s2->coord[X]) return 1;
if (s1->coord[Y] < s2->coord[Y]) return -1;
else if (s1->coord[Y] > s2->coord[Y]) return 1;
return 0;
}
float peek_next_site()
{
if (siteidx >= nsites) return -1;
return sites[siteidx].coord[X];
}
float trigger_next_event()
{
Wavefront *inact_event, *lowerbnd;
Wavefront *new_wf;
Site *newsite;
float ret, site_loc, inact_loc;
site_loc = peek_next_site();
inact_loc = EQ_min();
warn("site location %f, inact location %f\n",
site_loc, inact_loc);
if (site_loc >= 0 &&
(inact_loc < 0 || site_loc < inact_loc)) {
newsite = extractsite();
warn("site event %d(%f,%f) \n", newsite->sitenbr, newsite->coord[X],newsite->coord[Y]);
new_wf = WFcreate(newsite);
lowerbnd = WFlowerneighbor(new_wf);
if (lowerbnd->site->sitenbr >= 0)
report_edge(newsite, lowerbnd->site);
if (lowerbnd->WFup->site->sitenbr >= 0)
report_edge(newsite, lowerbnd->WFup->site);
if (lowerbnd->site->sitenbr >= 0
&& lowerbnd->WFup->site->sitenbr >= 0)
report_triple(lowerbnd->site, lowerbnd->WFup->site, new_wf->site);
WFinsert(lowerbnd, new_wf);
update_act_record(new_wf->WFup, UP);
update_act_record(new_wf->WFdown, DOWN);
ret = site_loc;
} else if (inact_loc >= 0) {
inact_event = EQextractmin();
warn("[%s] inactivation event for site %d(%f,%f) occured at %f!\n",__func__, inact_event->site->sitenbr, inact_event->site->coord[X],inact_event->site->coord[Y], inact_event->inact);
Wavefront *pre = inact_event->WFdown;
report_triple(inact_event->site, pre->site, inact_event->WFup->site);
WFdelete(inact_event);
report_edge(pre->site, pre->WFup->site);
update_act_record(pre, DOWN);
update_act_record(pre->WFup, UP);
ret = inact_loc;
} else if (finished) ret = NOEVENT;
else finished=1,ret = LASTEVENT;
warn("[%s] event at %f!\n", __func__, ret);
return ret;
}
Site *extractsite()
{
if (siteidx >= nsites) return NULL;
return &sites[siteidx++];
}
void report_edge (Site *s1, Site *s2)
{
DTedge *e;
e = var_array_elem(&dtedge_va, ndtedges++);
e->ends[0] = s1;
e->ends[1] = s2;
warn("edge %d between site %d(%f,%f) and %d(%f,%f)\n", ndtedges, s1->sitenbr, s1->coord[X], s1->coord[Y], s2->sitenbr, s2->coord[X], s2->coord[Y]);
}
void report_triple(Site *s1, Site *s2, Site *s3)
{
Triple *t;
bounding_rectangle(var_array_elem(&rectangle_va,ntriples),
s1, s2, s3, 1);
t = var_array_elem(&triple_va, ntriples++);
t->sites[0] = s1;
t->sites[1] = s2;
t->sites[2] = s3;
warn("triple (%d, %d, %d)\n",
t->sites[0]->sitenbr,
t->sites[1]->sitenbr,
t->sites[2]->sitenbr);
}
void update_act_record(Wavefront *w, int dir)
{
float offset, inact_location, rightmost;
Wavefront *upper = w->WFup;
Wavefront *lower = w->WFdown;
if (!upper || ! lower
|| upper->site->coord[X] < w->site->coord[X]
|| lower->site->coord[X] < w->site->coord[X])
return;
EQdelete(w);
offset = upper->site->coord[Y] - lower->site->coord[Y];
inact_location = w->site->coord[X] + offset;
rightmost = upper->site->coord[X] > lower->site->coord[X] ?
upper->site->coord[X]: lower->site->coord[X];
if (inact_location <= rightmost) {
Wavefront *pre = w->WFdown;
warn ("[%s] inactivaton record for site %d activated prematurely at %f\n", __func__, w->site->sitenbr, inact_location);
report_triple(w->site,pre->site,w->WFup->site);
WFdelete(w);
report_edge(pre->site, pre->WFup->site);
if (dir == UP) update_act_record(pre->WFup, UP);
else update_act_record(pre, DOWN);
} else {
EQinsert(w, inact_location);
warn("[%s] inactivation record for site %d at %f generated by %d and %d\n", __func__, w->site->sitenbr, inact_location, upper->site->sitenbr, lower->site->sitenbr);
}
}
void dump_sites()
{
int i;
for (i=0; i<nsites; i++)
warn("%d (%f,%f)\n", sites[i].sitenbr, sites[i].coord[X], sites[i].coord[Y]);
warn ("\n");
}