#include <stdlib.h> #include <stdio.h> #include <math.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; } bool Garden::Pixel( int x, int y, int d ) { if ( !d ) return value; int dim = (int) pow( 2, d ); if ( x < dim/2 ) { if ( y < dim/2 ) { //upper left return child[0].Pixel( x, y, d - 1 ); } else { //lower left return child[2].Pixel( x, y - dim / 2, d - 1 ); } } else { if ( y < dim/2 ) { //upper right return child[1].Pixel( x - dim/2, y, d - 1 ); } else { //lower right return child[3].Pixel( x - dim/2, y - dim / 2, d - 1 ); } } } void Garden::Grow( Rule* rule ) { CreateChildren( rule ); ConnectChildren(); } 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; }
# | Change | User | Description | Committed | |
---|---|---|---|---|---|
#2 | 4790 | Sam Stafford |
SquareCraft optimizations... patterns are now only recalculated when the rules change, not when the depth or colors do. |
||
#1 | 4776 | Sam Stafford | A simple Qt frontend to the "squaregarden" algorithms. | ||
//guest/sam_stafford/garden/src/Garden.cpp | |||||
#1 | 4772 | Sam Stafford | Something I've been doodling with. |