
#include <stdio.h>
#include <math.h>
#include "glut.h"
#include "eventshrub.h"


float EventShrub::colors[6][3] = { { 1.0, 0.0, 0.0} , { 0.0, 1.0, 0.0} , 
							{ 0.0, 0.5, 0.5} , { 0.5, 0.0, 0.5} , 
							{ 0.5, 0.5, 0.0} , { 0.0, 0.0, 1.0} };

float EventShrub::ymin = 0.0;
float EventShrub::xv = 0.0;
float EventShrub::xv_min = 0.0;

EventShrub::EventShrub() : Flag(0) , resolution(60) , n(0) { 

}

void EventShrub::DrawCircle(int flag) {

	int i;
	int segments[6];
	int numsegments;
	float incr, theta;
	float segmentangle;
	float adj,adj1,adj2;
	int no_signature;
	float cx, cy;

	if (flag==0) { // horizontal base
		cx = x; cy = y;
	} else if (flag==1) { // vertical base
		cx = xv; cy = yv;
	}
	
	numsegments = 0;
	for (i=0;i<6;i++) {
		if (Flag & 1 << i) {
			segments[numsegments] = i;
			numsegments++;
		}
	}

	no_signature = 0;
	if (numsegments==0) {
		numsegments = 1;
		no_signature = 1;
	}

	incr = 2.0*PI/(float)resolution;
	segmentangle = 2.0*PI/(float)numsegments;


	for (i=0;i<numsegments;i++) {
		if (no_signature==1) {
			glColor3f(0.5,0.5,0.5);
		} else {
			glColor3f(colors[segments[i]][0], colors[segments[i]][1], colors[segments[i]][2]);
		}
		glBegin(GL_POLYGON);
		for (theta = segmentangle*(float)i; theta<(segmentangle*(float)(i+1)); theta += incr) {
			glVertex3f(cx+r*cos(theta),cy+r*sin(theta),0.0);
		}
		glVertex3f(cx+r*cos(segmentangle*(float)(i+1)),cy+r*sin(segmentangle*(float)(i+1)),0.0);
		glEnd();
	}
	
}

void EventShrub::DrawBase() {

	glEnable(GL_BLEND);
	glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
	glColor4f(0.5,0.5,0.5,0.3);
	glBegin(GL_TRIANGLES);
	glVertex3f(x,y,0.1);
	glVertex3f(x1,ymin,0.1);
	glVertex3f(x2,ymin,0.1);
	glEnd();
	glDisable(GL_BLEND);
	glColor4f(0.5,0.5,0.5,1.0);
	glBegin(GL_LINES);
	glVertex3f(x,y,0.1);
	glVertex3f(x,ymin,0.1);
	glEnd();

}

void EventShrub::DrawVertBase() {

	glEnable(GL_BLEND);
	glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
	glColor4f(0.5,0.5,0.5,0.3);
	glBegin(GL_TRIANGLES);
	glVertex3f(xv,yv,0.1);
	glVertex3f(xv_min,y1,0.1);
	glVertex3f(xv_min,y2,0.1);
	glEnd();
	glDisable(GL_BLEND);
	glColor4f(0.5,0.5,0.5,1.0);
	glBegin(GL_LINES);
	glVertex3f(xv,yv,0.1);
	glVertex3f(xv_min,yv,0.1);
	glEnd();
	//printf("shrub %f %f %f %f %f\n", x, x1, x2, y, ymin);

}


void EventShrub::Draw() {
	DrawCircle(0);
	DrawBase();
}

void EventShrub::DrawVert() {
	DrawCircle(1);
	DrawVertBase();
}

EventsViz::EventsViz(int sx, int sy, int xs, int ys) : Visualization(sx,sy,xs,ys) , num_events(0) {
	EventShrub::ymin = sy;
}

void EventsViz::SetVerticalDimensions(int sx, int sy, int xs, int ys) {
	vstartx = sx; vstarty = sy; vxsize = xs; vysize = ys;
	EventShrub::xv = (float)sx + 0.5 * (float)xs;
	EventShrub::xv_min = (float)sx;
}

void EventsViz::Draw() {

	int i;

	glMatrixMode(GL_PROJECTION);
	glLoadIdentity();
	gluOrtho2D(startx, startx+xsize, starty, starty+ysize);
			// left, right, bottom, top
	glViewport(startx, starty, xsize, ysize);
			// startx, starty, xsize, ysize
			// coordinates begin from lower left corner of window
	glMatrixMode(GL_MODELVIEW);
	glLoadIdentity();
    glDisable(GL_TEXTURE_2D);
	glDisable(GL_LIGHTING);

	for (i=0;i<num_events;i++) events[i].Draw();

}


void EventsViz::DrawVert() {

	int i;

	glMatrixMode(GL_PROJECTION);
	glLoadIdentity();
	gluOrtho2D(vstartx, vstartx+vxsize, vstarty, vstarty+vysize);
			// left, right, bottom, top
	glViewport(vstartx, vstarty, vxsize, vysize);
			// startx, starty, xsize, ysize
			// coordinates begin from lower left corner of window
	glMatrixMode(GL_MODELVIEW);
	glLoadIdentity();
    glDisable(GL_TEXTURE_2D);
	glDisable(GL_LIGHTING);

	for (i=0;i<num_events;i++) {
		if ((events[i].show_begin==1) && (events[i].show_end==1)) {
			events[i].DrawVert();
		}
	}

}

void EventsViz::SettleHeights() {
	
	int i,j;
	float intervals[128][2];
	int nintervals;
	float es;
	float proposedy, conflictedEnd;
	int conflicted;

	for (i=0;i<num_events;i++) {
		es = events[i].x - events[i].r;
		nintervals = 0;
		for (j=0;j<i;j++) {
			if (events[j].x + events[j].r > es) {
				intervals[nintervals][0] = events[j].y - events[j].r;
				intervals[nintervals][1] = events[j].y + events[j].r;
				nintervals++;
			}
		}
		conflicted = 1;
		conflictedEnd = 0.01;
		proposedy = conflictedEnd + events[i].r;
		while (conflicted) {
			conflicted = 0;
			for (j=0;j<nintervals;j++) {
				if (((intervals[j][0] < proposedy + events[i].r) && (intervals[j][0] >= proposedy - events[i].r)) ||
					((intervals[j][1] <= proposedy + events[i].r) && (intervals[j][1] > proposedy - events[i].r)) ||
					((proposedy + events[i].r <= intervals[j][1]) && (proposedy + events[i].r > intervals[j][0]))) {
					if (intervals[j][1] > conflictedEnd) conflictedEnd = intervals[j][1];
					proposedy = conflictedEnd + events[i].r + 0.001;
					conflicted = 1;
				}
			}
		}
		events[i].y = proposedy;
	}
	for (i=0;i<num_events;i++) {
		events[i].y += starty;
	}
}

