#include <stdlib.h>
#include <stdio.h>
#include <GL/glut.h>
#include "Garden.h"
Garden::Garden(void)
{
u = d = l = r = child = parent = 0x0;
connected = false;
depth = 0;
value = true;
s = p = 0;
child = 0x0;
dr = dg = db = 0.0;
}
Garden::~Garden(void)
{
if ( child ) delete[4] child;
}
void Garden::Render()
{
if ( !child ) //leaf node, render self
{
if ( value ) glColor3f( 0 + dr, 0.4 + dg, 0.4 + db );
else glColor3f( dr, dg, db );
glBegin( GL_QUADS );
glVertex2f( 0, 0 );
glVertex2f( 0, 1 );
glVertex2f( 1, 1 );
glVertex2f( 1, 0 );
glEnd();
return;
}
// render children
glPushMatrix();
glScalef( 0.5, 0.5, 1.0 );
glTranslatef( 0, 1, 0.0 );
child[0].Render();
glPopMatrix();
glPushMatrix();
glScalef( 0.5, 0.5, 1.0 );
glTranslatef( 1, 1, 0 );
child[1].Render();
glPopMatrix();
glPushMatrix();
glScalef( 0.5, 0.5, 1.0 );
glTranslatef( 0, 0, 0.0 );
child[2].Render();
glPopMatrix();
glPushMatrix();
glScalef( 0.5, 0.5, 1.0 );
glTranslatef( 1, 0, 0.0 );
child[3].Render();
glPopMatrix();
}
void Garden::Grow( Rule* rule )
{
CreateChildren( rule );
ConnectChildren();
}
void Garden::Tend( Rule* rule )
{
if ( child )
{
for ( int c = 0 ; c < 4 ; c++ )
child[c].Tend( rule );
return;
}
int ncount = 0;
if ( u && u->value ) ncount++;
if ( d && d->value ) ncount++;
if ( l && l->value ) ncount++;
if ( r && r->value ) ncount++;
if ( u && u->l && u->l->value ) ncount++;
else if ( l && l->u && l->u->value ) ncount++;
if ( u && u->r && u->r->value ) ncount++;
else if ( r && r->u && r->u->value ) ncount++;
if ( d && d->l && d->l->value ) ncount++;
else if ( l && l->d && l->d->value ) ncount++;
if ( d && d->r && d->r->value ) ncount++;
else if ( r && r->d && r->d->value ) ncount++;
value = rule->Tend( value ? true : false , ncount );
}
void Garden::ClearScratch()
{
s = 0;
p = 0;
if ( child )
{
for ( int c = 0 ; c < 4 ; c++ )
child[c].ClearScratch();
}
}
Fitness Garden::GetFitness( float adr, float adg, float adb )
{
Fitness fit;
fit.clumpsize = 0;
fit.perimeter = 0;
fit.g = this;
if ( child ) return child[0].GetFitness( adr, adg, adb );
if ( s )
{
//find next unchecked garden node
Garden* g = this;
while ( g )
{
while ( g->r )
{
if ( !g->s ) return g->GetFitness( adr, adg, adb );
g = g->r;
}
if ( !g->s ) return g->GetFitness( adr, adg, adb );
if ( !g->d ) return fit;
g = g->d;
while ( g->l )
g = g->l;
}
}
s = 1;
dr = adr;
dg = adg;
db = adb;
if ( !u || u->value != value ) p++;
if ( !d || d->value != value ) p++;
if ( !l || l->value != value ) p++;
if ( !r || r->value != value ) p++;
if ( u && u->value == value && !u->s )
{
fit = u->GetFitness( adr, adg, adb );
s += fit.clumpsize;
p += fit.perimeter;
}
if ( d && d->value == value && !d->s )
{
fit = d->GetFitness( adr, adg, adb );
s += fit.clumpsize;
p += fit.perimeter;
}
if ( l && l->value == value && !l->s )
{
fit = l->GetFitness( adr, adg, adb );
s += fit.clumpsize;
p += fit.perimeter;
}
if ( r && r->value == value && !r->s )
{
fit = r->GetFitness( adr, adg, adb );
s += fit.clumpsize;
p += fit.perimeter;
}
fit.clumpsize = s;
fit.perimeter = p;
return fit;
}
void Garden::CreateChildren( Rule* rule )
{
depth++;
if ( child )
{
for ( int c = 0 ; c < 4 ; c++ )
child[c].CreateChildren( rule );
return;
}
child = new Garden[4]; //ul, ur, dl, dr
for ( int c = 0 ; c < 4 ; c++ )
{
child[c].parent = this;
}
Quad vals = rule->Grow( value, u && u->value, r && r->value, d && d->value, l && l->value );
child[0].value = vals.ul;
child[1].value = vals.ur;
child[2].value = vals.dl;
child[3].value = vals.dr;
}
void Garden::ConnectChildren()
{
if ( !child ) return;
if ( connected )
{
for ( int c = 0 ; c < 4 ; c++ )
child[c].ConnectChildren();
return;
}
if ( u && u->child )
{
child[0].u = u->child + 2;
child[1].u = u->child + 3;
}
if ( d && d->child )
{
child[2].d = d->child + 0;
child[3].d = d->child + 1;
}
if ( l && l->child )
{
child[0].l = l->child + 1;
child[2].l = l->child + 3;
}
if ( r && r->child )
{
child[1].r = r->child + 0;
child[3].r = r->child + 2;
}
child[0].r = child + 1;
child[0].d = child + 2;
child[1].l = child + 0;
child[1].d = child + 3;
child[2].r = child + 3;
child[2].u = child + 0;
child[3].l = child + 2;
child[3].u = child + 1;
connected = true;
}
int Garden::ClumpCount()
{
if ( !child ) return s ? 1 : 0;
int acc = 0;
for ( int c = 0 ; c < 4 ; c++ )
acc += child[c].ClumpCount();
return acc;
}
int Garden::TotalCount()
{
if ( !child ) return value ? 1 : 0;
int acc = 0;
for ( int c = 0 ; c < 4 ; c++ )
acc += child[c].TotalCount();
return acc;
}