//int doffire(unsigned tmax=1000000, unsigned short fmatch=200, unsigned int randPlant=1, unsigned int clustPlant=0, unsigned short burnAge=1, unsigned short burnPropAge=1, int rhoRocks=0, int doSQL=1, float pImmune=0, int nnnAge=0) {
int doffire(unsigned int tmax=1000000, unsigned int fmatch=125, int doSQL=2, float pImmune=0, float kImmune=1, std::string immCode=std::string("100") ) {
	// immCode: [1]: cluster level, [2]: fire-front elements, [3]: each new element. (evaluate immunity at these times).
	//printf("test immCode: %s\n", immCode.c_str());
	if (immCode.at(2)==std::string("1")[0] ) printf("and we are not doing perim-level immunity.\n");
	bool doImPrim=0, doImFlameFront=0, doImFireElement=0;
	if (immCode.at(2)==std::string("1")[0] ) doImPrim=1;
	if (immCode.at(1)==std::string("1")[0] ) doImFlameFront=1;
	if (immCode.at(0)==std::string("1")[0] ) doImFireElement=1;
	
	
	int aveRho = 0, aveVol=0;
	int burnAge=1, burnPropAge=1;
	int nTreesOnGrid=0;
	
	std::string simName("ForestFire5c");
	std::string simPramComment("single-pass fire propagation/immunity evaluation");
	//
	unsigned short rFire = 1;
	unsigned int nBurning = 1;
	unsigned short dnBurning = 1;
	int thisXY, xFire, yFire;
//	int thisStatus;
	int * thisSquare, * fireSquare;
	unsigned int nBurnedTotal=0, nFires=0;  // number of elements burning, new Elements burning...
	float aveTreeAge=0;
	//signed int grids[(ymax+2)*(xmax+2)];
	int *grids = new int[(ymax+2)*(xmax+2)];
	//int *directions = new int[4];
	//*directions={1,-1, xmax+2, -(xmax+2)};
	int directions[4]={1,-1, xmax+2, -(xmax+2)};
	//int randDirs[4]={1,-1, xmax+2, -(xmax+2)};	// new array to be randomized
	int *newOrder = new int[4];
	// v9:
	int *fireList = new int[(ymax)*(xmax)];
	unsigned int *fcounts = new unsigned int[(ymax)*(xmax)];
	unsigned short newFireElements=0;		// [x, x, x, x, x, x[nBurning], x, x, x, x[dnBurning], x, x, x, x[newFireElements] ]: old-fire, current flame-front, new elements.
	unsigned int totalFireCount=0;
	//
	bool doQuench = 0;
	//
	float frandImmune=0;
	int randImmune = 0;
	//
	//unsigned int rhoRocks = 10;	// of 100
	// initialize?
	srand(time(NULL));	// eventually, we have to be smarter about this and use independent random sets. see Gleb's random number gens.
	for (unsigned int i=0; i<(xmax+2)*(ymax+2); i++) {
		grids[i]=0;
		// seed the grid with some trees
		if (rand()%(xmax/2)==1 and i%(xmax+2)!=0 and i%(xmax+2)!=(xmax+1) and i>(xmax+2) and i<((xmax+2)*(ymax+1)) ) {
			grids[i]=1;
			nTreesOnGrid ++;
			};
		//if (i>(xmax+2)*(ymax+1)) printf("initializing grid %d\n", i);
		//yodapause();
		};
	//printf("random grid established...\n");
	//printGrid(&grids[0], 1, xmax, ymax);
	//
	char DB[]="ForestFire";
	char HOST[]="localhost";
	char USER[]="myoder";
	char PASSWORD[]="yoda";
	mysqlpp::Connection myconn(DB, HOST, USER, PASSWORD);
	mysqlpp::Query myquery=myconn.query();
	//mysqlpp::Result res1;
	mysqlpp::StoreQueryResult res1;
	int intKey;
		
	//unsigned int fcounts[xmax*ymax];
		for (unsigned int i=0; i<xmax*ymax; i++) {
			//fcounts[i]=0;
			//fireList[i]=0;
			*(fcounts + i)=0;
			*(fireList + i)=0;
			};
	if (doSQL==1 or doSQL==5 or doSQL==25) {	
		//
		// insert a new row for this sim-run:
		myquery.reset();
		printf("insert simprams.\n");
		myquery << "insert into ForestFire.SimPrams (`SimName`, `xmax`, `ymax`, `sparkInterval`, `burnAge`, `tmax`, `nRand`, `pImmune`, `kImmune`, `Comment`) values (%0q, %1q, %2q, %3q, %4q, %5q, %6q, %7q, %8q, %9q )";
		myquery.parse();
		// note: simIndex(auto-int) and dtTime (default TIMESTAMP) set automatically.
		//myquery.execute(simName.c_str(), simName.c_str(), xmax, ymax, fmatch, burnAge, tmax, randPlant, clustPlant, kmax, simPramComment.c_str());
		 myquery.execute(simName.c_str(), xmax, ymax, fmatch, 1, tmax, 1, pImmune, kImmune, simPramComment.c_str());
		//
		// now, get the integer key for this simulation:
		// note that this could be accomplished with one call (optimal if MySQL calls have high overhead)
		// by writing a SPROC on the MySQL side.
		// also see the mysql_insert_id() (C API) and LAST_INSERT_ID() (SQL) functions, by which we should be ablt to automatically retrieve the indexID.
		myquery.reset();
		printf("fetch simIndex.\n");
		myquery << "select max(simIndex) from ForestFire.SimPrams";
		myquery.parse();
		res1 = myquery.store(simName.c_str(), simName.c_str());
		intKey = res1.at(0).at(0);
		}; // doSQL
	//
	//printf("beginnn.\n");
	//for (unsigned int i=0; i<=tmax; i++) {
	unsigned int i=0;		// just so other bits don't break...
	while (totalFireCount<=tmax) {
		i++;		// this might overflow i guess. if so... figure out something.
		//if (doSQL==5 or doSQL==6) if(i%1000000 == 0) printf("%d million\n", i/1000000);
		if (doSQL==6) if(i%1000000 == 0) printf("%d million\n", i/1000000);

		if (doSQL==16) {
			if(i%100000 == 0) {
				// printf("%d million\n", i/1000000);
				aveRho=0;
				aveVol=0;
				for (unsigned int k=0; k<(xmax+2)*(ymax+2); k++) {
					if (*(grids+k)>0 and *(grids+k)<rockAge) {
						aveRho = aveRho + 1;
						aveVol = aveVol + *(grids+k);
						};
					};
				//printf("mils,\t Rho,\t Vol,\t %d, %f, %f\n", i/1000000, float(aveRho)/float(xmax*ymax), float(aveVol)/float(xmax*ymax));
				printf("%d, %f, %f\n", i/1000000, float(aveRho)/float(xmax*ymax), float(aveVol)/float(xmax*ymax));
				};
			};
		//
		// PLANT A TREE:
		// select a grid for tree planting:
			//thisX = rand()%xmax+1;
			//thisY = rand()%ymax+1;
			//thisSquare = &grids[0] + thisX + (xmax+2)*thisY;	// point to the current square...
			// for speed, select one random number; if we land on a rock, then just skip. there aren't many rocks.
			thisXY = xmax+3 + rand()%((xmax+2)*ymax-1);
			thisSquare = grids + thisXY;
			// if (*thisSquare<rockAge) {
			if (*thisSquare==0) {
				*thisSquare = *thisSquare + 1;
				nTreesOnGrid ++;
				};

	// we've planted a tree. do we throw a match?
		// we can do this two ways. we can trow a match every M steps or set a 
		// 1/M probability every time.
		// for now, we're being super simple; throw a match every 'fmatch' steps:
		// throw a match with 1/fmatch probability. generate a random number beteen 1 and fmatch; each number appears with freq. 1/fmatch
		//ffmatch = float(i+1)/float(fmatch);
		//if (float(int(ffmatch))==ffmatch and i>xmax) {
		//if (rand()%((1+prefPlant)*fmatch)==1) {
		
		if (rand()%fmatch==1) {
			//yodapause();
			// throw a match.
			xFire = rand()%xmax+1;
			yFire = rand()%ymax+1;
			fireSquare = &grids[0] + xFire + (xmax+2)*yFire;
			//printf("match: (%d, %d) :: %d/%d\n", xFire, yFire, *fireSquare, *(&grids[0] + (xFire + (xmax+2)*yFire)));
			//yodapause();
			//
			//printf("now evaluate *fireSquare, etc. %d\n", *fireSquare);
			//if (getGridStatus(*fireSquare, i) >= burnAge and getGridStatus(*fireSquare, i) < rockAge) {
			if (*fireSquare >= burnAge and *fireSquare < rockAge) {				
				// initiate a new fire.
				// now, we have three places to test quench-immunity:
				// 1) after each new step of front propagation
				// 2) after each burning element is tested against its NN
				// 3) after each element is added.
				// when the sequence of testing is fully randomized, we can test at any level.
				//
				// use the list-method (see v9a comments at the top) to propagate the fire.
				//printf("set 0-grid...\n");
				//*fireSquare = -(*fireSquare);	// we could remove the square; we track the fire in a list (=0), but we want to be able to plot the grid...
				//*fireSquare=0;
				//printf("set fireSquare... %d, %d, %d: %d\n",xFire, yFire, xmax, (xFire + (xmax+2)*yFire));
				totalFireCount++;
				*fireSquare=-1;
				fireList[0]=(xFire + (xmax+2)*yFire);	// or should we use an array of addresses?
				//printf("set fireSquare done\n");
				//
				rFire = 1;
				dnBurning = 1;
				nBurning = 0;
				newFireElements=0;
				//
				//int yFireMin = int(yodacode::greaterOf((yFire-rFire), 1));	// we always start with a 1 squar boundary. we might, however, encounter the edges.
				//int yFireMax = int(yodacode::lesserOf((yFire+rFire), float(ymax)));
				//int xFireMin = int(yodacode::greaterOf(float(xFire-rFire), 1));
				//int xFireMax = int(yodacode::lesserOf(float(xFire+rFire), float(xmax)));
				//
				//printf("fire range: %d, %d, %d, %d\n", yFireMin, yFireMax, xFireMin, xFireMax);
				//printf("preplot\n.");
				//
				//plotGrid(&grids[0],i, xmax, ymax);
				if (doSQL==0) {
					printGrid(&grids[0], i, xmax, ymax);
					};
				//while (dnBurning > 0) {
				doQuench = 0;
				//nFireSteps=0;	// steps fire has propagated, max dist/radius from flash-point. effectively time it's been burning.
				//printf("fire started at %d. now propagate.\n", xFire + (xmax+2)*yFire);
				while (dnBurning > 0 and doQuench==0) {
					//dnBurning=0;
					// evaluate neighbors of current burn front (nBurning-1 < i < (nBurning-1)+dnBurning
					unsigned int fireIndex=nBurning;
					//unsigned int newFireIndex=0;
					unsigned int currentElementIndex;
					//printf("fire front burning. fireIndex=%d\n", fireIndex);
					int * randomFireSequence = new int[dnBurning];
					int * testSeq = new int[dnBurning];
					for (int itest=0; itest<dnBurning; itest++) {
						*(testSeq + itest) = itest;
						}
					scrambleList(testSeq, randomFireSequence, dnBurning);
					delete [] testSeq;
					//if (dnBurning>1) randomSequence(randomFireSequence, dnBurning);	// randomize order in which we evalueate fire propagation.
					//for (int ilist=0; ilist<dnBurning; ilist++) {
					//	printf("randomSequence[%d]=%d\n", ilist, randomFireSequence[ilist]);
					//	};
					//
					while (fireIndex < (nBurning+dnBurning) and doQuench==0) {
						//newFireIndex=fireIndex-nBurning;
						currentElementIndex=nBurning+randomFireSequence[fireIndex-nBurning];	// this is long-winded because i'm building it off the simpler non-randomized model.
						//printf("fire index: %d (%d, %d, %d, %d)\n", fireIndex-nBurning, fireIndex, nBurning, dnBurning, currentElementIndex);
						//printf("failing here? %d, %d, %d\n", nBurning, dnBurning, fireIndex-nBurning);
					
						//currentElementIndex=nBurning+randomFireSequence[fireIndex-nBurning];
					//	printf("nope. ");
						
						
						// check for fire:
						// to maintain symmetry, randomize directions:
						// randDirs
						//scrambleList(directions, randDirs, 4);
						//int ordr[4]={0,1,2,3};
						//int newOrder[4];
						randomSequence(newOrder,4);
						//scrambleList(ordr, newOrder, 4);	// i think this is killing the random number generator.
						//printf("newOrder: %d, %d, %d, %d\n" , newOrder[0], newOrder[1],newOrder[2],newOrder[3]);
						
						for (int idir=0; idir<4; idir++) {
							// note: this loop format may facilitate randomization of direction later on...
							// nothing randomized:
							/*
							// I.
							if (grids[fireList[fireIndex] + directions[idir]]==1) {
								grids[fireList[fireIndex] + directions[idir]]=-1;
								fireList[nBurning + dnBurning + newFireElements]=fireList[fireIndex]+directions[idir];
								newFireElements++;
								};
							*/
							// order of each element (NN) randomized:
							/*
							// II.
							if (grids[fireList[fireIndex] + directions[newOrder[idir]]]==1) {
								grids[fireList[fireIndex] + directions[newOrder[idir]]]=-1;
								fireList[nBurning + dnBurning + newFireElements]=fireList[fireIndex]+directions[newOrder[idir]];
								newFireElements++;
								};
							*/
							// III.
							// each element (NN) and order of flame-front randomized:
							//printf("currentElement: %d\n", currentElementIndex);
							//printf("grid index: %d, %d, %d\n" , fireList[currentElementIndex], directions[newOrder[idir]], newOrder[idir]);
							//printf("segmentation fault test: grid-val (%d)\n", grids[fireList[currentElementIndex] + directions[newOrder[idir]]]);
							if (grids[fireList[currentElementIndex] + directions[newOrder[idir]]]==1) {
								//
								// add an entry to fireList. at the end of fireList [nBurning+dnBurning+newFireElements], add the fire location value,
								// fireList[currentElementIndex] + direction[]
								if (doQuench==0) {
									grids[fireList[currentElementIndex] + directions[newOrder[idir]]]=-1;
									fireList[nBurning + dnBurning + newFireElements]=fireList[currentElementIndex]+directions[newOrder[idir]];
									newFireElements++;
									};
								//if (immCode[2]=="1") {
								// so, do we do this before or after we evaluate the element? by doing this after we propagate the first step (so
								// fires are always k>1; alternatively we could use 1/(k+1)^p), we can use Pimmune>1 .
								if (doImFireElement) {
									// evaluate immunity (as each new element burns):
									//if (testQuench((nBurning+dnBurning+newFireElements), pImmune, kImmune)) {
									randImmune = rand()%RAND_MAX;
									frandImmune = float(randImmune)/RAND_MAX;
									if (frandImmune < (pImmune/pow(float(nBurning+dnBurning+newFireElements), kImmune)) ) {
										idir=4;
										doQuench=1;
										
										//printf("fire quenched during element-propagation: %d/%d\n", nBurning+dnBurning+newFireElements, fireIndex+1);
										//printGrid(&grids[0], i, xmax, ymax);
										//continue;
										};
									};
								};
							//
							// MFI (after each element is tested to the fire). this is only allowed at this step for type III propagation (above). if we apply immunity
							// as each element is added and elements are added in some geometrical sequence (aka, around the fire-front), we break the symmetry and break
							// SOC between integer values of L^2. by itself, using the list method (in particular when we randomize direction) might fix this problem,
							// since it breakes down the spiral geometry of our former concentric square propagation.
								
							};
						fireIndex++;

						// evaluate immunity (as each burning (fire-front) element propagates):
						//if (testQuench((nBurning+dnBurning+newFireElements), pImmune, kImmune)) {
						//if (immCode[1]=="1") {
						if (doImFlameFront) {
							randImmune = rand()%RAND_MAX;
							frandImmune = float(randImmune)/RAND_MAX;
							if (frandImmune < (pImmune/pow(float(nBurning+dnBurning+newFireElements), kImmune)) ) {
								//printf("quenched a fire at k=%d, Pq=%f/%f\n", (nBurning+dnBurning+newFireElements), pImmune/pow((nBurning+dnBurning+newFireElements), kImmune), frandImmune);
								doQuench=1;
								};
							};
					 	//
						//
						
						};
					// this round of propagation is over (new elements have propagated to NN).
					nBurning = nBurning + dnBurning;
					dnBurning=newFireElements;
					newFireElements=0;
					delete [] randomFireSequence;
					//
					// evaluate immunity (after each full propagation step):
					//if (immCode[0]=="1") {
					if (doImPrim) {
						// at this point, the first step of propagation has occurred, so nominally we can use pImmune>1.
						// arguably, this creates a new characteristic size; maybe the omori-type immunity is a better idea?
						//if (testQuench((nBurning+dnBurning+newFireElements), pImmune, kImmune)) {
						randImmune = rand()%RAND_MAX;
						frandImmune = float(randImmune)/RAND_MAX;
						if (frandImmune < (pImmune/pow(float(nBurning+dnBurning+newFireElements), kImmune)) ) {
						//if (frandImmune < (pImmune/(1+float(nBurning+dnBurning+newFireElements)/kImmune) ) ){
							//idir=4;
							doQuench=1;
							};
						};
					//printGrid(&grids[0], i, xmax, ymax);
					// g1.plot_xy(vfireX, vfireY, "");
					};	// end fire still burining
				//
				// fire is over:
				nFires++;
				nBurnedTotal = nBurnedTotal + nBurning;
				nTreesOnGrid = nTreesOnGrid-nBurning;
				//printf("fire over; %d burned.\n", nBurning);
				fcounts[nBurning-1]++;
				// printf("fcounts[%d]: %d\n", nBurning-1, fcounts[nBurning-1]);
				//plotGrid(&grids[0], xmax, ymax);
				//printGrid(&grids[0], i, xmax, ymax);
				if (doSQL==0) {
					printGrid(&grids[0], i, xmax, ymax);
					};
				// write fire to MySQL:
				if (doSQL==1) {
					// printf("fire size, nFires, totalBurned: (%d) (%d) (%d)\n", nBurning, nFires, nBurnedTotal);
					myquery.reset();
					myquery << "insert into ForestFire.ForestFires (simIndex, t, xSpark, ySpark, nBurned, nTrees) values (%0q, %1q, %2q, %3q, %4q, %5q) ";
					myquery.parse();
					myquery.execute(intKey, i, xFire, yFire, nBurning, nTreesOnGrid);
					//yodapause();
					};
				if (doSQL==3) {
					printf("fire at time %d\n", i);
					if (nBurning>=xmax/5) plotGrid (&grids[0], i, xmax, ymax, burnPropAge);
					};
				if (doSQL==4) {
					if (nBurning>=xmax/5) plotGridImg (&grids[0], i, xmax, ymax, burnPropAge);
					};
				//
				// fires finished burning; extinguish:
				unsigned int icleanup=0;
				while (fireList[icleanup]!=0) {
				//while (icleanup<nBurning+dnBurning+newFireElements){
				//while (icleanup<(xmax*ymax)){
					grids[fireList[icleanup]]=0;
					fireList[icleanup]=0;
					icleanup++;
					};
				nBurning = 0;
				dnBurning=0;
				newFireElements=0;
				//printGrid(&grids[0], i, xmax, ymax);
				//fireIndex=0;
				}; //else printf("no tree at match point.\n");	// if match -> tree...
			}; // if match-time

		// do we initialize with 0?
		//printf("ary element 0,i: %d", grids[0][i]);
		};	// end sim-steps.

	// end simulation.
	//printf("doSQL: %d\n", doSQL);
	// doSQL's:
	// 0: 'print-grid" fires
	// 1: full SQL: insert each forest fire data-set into ForestFires
	// 2: print summary to screen. use this for direct gnuplot calls, " plot '<./ffire4...'" 
	// 3: Print each fire to screen; "plotGrid" each fire nBurning>(25) print summary to screen at end
	// 4: plotGridImg each fire nBurning>(20); print summary to screen,
	// 5: SQL: insert just summary data to SQL; prints progress by million (will screw up plotting)
	// 6: report summary, progress by million.
	// 11: return to standard-output the last grid in full. use to make an image of the final grid.
	//
	// for super long runs (10^9 steps), it looks like the mysql connection times out, so all is lost.
	// renew the connection. 
	//
//	if (myconn.connected()==0) myconn.connect(DB, HOST, USER, PASSWORD);
	mysqlpp::Connection newconn(DB, HOST, USER, PASSWORD);
	mysqlpp::Query newquery=myconn.query();
	//mysqlpp::Result res1;

	//mysqlpp::Query myquery=myconn.query();
	//mysqlpp::Result res1;
	// end-o-run summaries (print):
	
	//printf("xmax*ymax = %d; %d, %d\n", xmax*ymax, ymax, xmax);
	if (doSQL==2  or doSQL==25 or doSQL==3 or doSQL==4 or doSQL==6) {
		//printf("dosql=2 or something. we should get a summary.");
		for (unsigned int i=0; i<(xmax*ymax); i++) {
			if (fcounts[i]!=0) {
				printf("%d\t%d\n", i+1, fcounts[i]);
				//printf("%d\t%d\n", i+1, i);
				//printf("%d,\t%d\n", i+1, fcounts[i]);
				}
			else {
				//printf("finished.\nfire size, nFires, totalBurned: (%d) (%d) (%d)\n", nBurning, nFires, nBurnedTotal);
				};
			};
		};
	//printf("moving past dosql2\n");
	if (doSQL==5 or doSQL==25 ) { // no plots, just a summary -> SQL
		//
		for (unsigned int i=0; i<(xmax*ymax); i++) {
			// if (fcounts[i]!=0) printf("%d\t%d\n", i+1, fcounts[i]);
		//	printf ("sql bits: %d, %d, %d, %d\n", intKey, tmax, i+1, fcounts[i]);
			newquery.reset();
			newquery << "insert into ffcounts (simIndex, tmax, nBurned, nEvents) values (%0q, %1q, %2q, %3q)";
			newquery.parse();
			newquery.execute(intKey, tmax, i+1, fcounts[i]);
			//printf("%d,\t%d\n", i+1, fcounts[i]);
			};				
		};
	//printf("moving past dosql5,25\n");
	// return the final grid in full and give an average density at the end...?
	if (doSQL==11) {
		for (unsigned int i=0; i<(xmax+2)*(ymax+2); i++) {
			printf ("%d,\t%d,\t%d\n", i-int(i/(xmax+2))*(xmax+2), i/(xmax+2), getGridStatus(*(grids+i), tmax));
			};
		};
	//g1.reset_plot();
	//g1.plot_xyz(vx, vy, vGridStat, "xyz plot of TreesPlanted");

	//yodacode::yodapause();
	//
	// clean up memory?
	delete [] grids;
	delete [] fireList;
	delete [] fcounts;
	//delete [] directions;
	return 0;
	//return &grids[0];
	};
//int doffire(unsigned tmax=1000000, unsigned short fmatch=200, unsigned int randPlant=1, unsigned int clustPlant=0, unsigned short burnAge=1, unsigned short burnPropAge=1, int rhoRocks=0, int doSQL=1, float pImmune=0, int nnnAge=0) {
int doffire(unsigned int tmax=1000000, unsigned int fmatch=125, int doSQL=2, float pImmune=0, float kImmune=1) {
	// burn toplolgy: do we nave nnn burning
//	if (nnnAge==0) nnnAge=54321;	// trees age>nnnAge will spread to next nearest neighbors. use "0" pram for no nnn connectivity; nothing should ever get this old.
	int aveRho = 0, aveVol=0;
	int burnAge=1, burnPropAge=1;
	int nTreesOnGrid=0;
	int nFireSteps=0;	// the number of steps the fire has propagated (the radius, or more correctly the maximum distance of a burning element from the flashpoint)

	std::string simName("ForestFire5c");
	std::string simPramComment("single-pass fire propagation/immunity evaluation");
	//
	unsigned short rFire = 1;
	unsigned int nBurning = 1;
	unsigned short dnBurning = 1;
	int thisXY, xFire, yFire;
//	int thisStatus;
	int * thisSquare, * fireSquare;
	unsigned int nBurnedTotal=0, nFires=0;  // number of elements burning, new Elements burning...
	float aveTreeAge=0;
	//signed int grids[(ymax+2)*(xmax+2)];
	int *grids = new int[(ymax+2)*(xmax+2)];
	bool doQuench = 0;
	//
	float frandImmune=0;
	int randImmune = 0;
	//
	//unsigned int rhoRocks = 10;	// of 100
	// initialize?
	srand(time(NULL));	// eventually, we have to be smarter about this and use independent random sets. see Gleb's random number gens.
	for (unsigned int i=0; i<(xmax+2)*(ymax+2); i++) {
		grids[i]=0;
		// seed the grid with some trees
		if (rand()%(xmax/2)==1 and i%(xmax+2)!=0 and i%(xmax+2)!=(xmax+1) and i>(xmax+2) and i<((xmax+2)*(ymax+1)) ) {
			grids[i]=1;
			nTreesOnGrid ++;
			};
		//yodapause();
		};
	//printf("random grid established...\n");
	//printGrid(&grids[0], 1, xmax, ymax);
	//
	char DB[]="ForestFire";
	char HOST[]="localhost";
	char USER[]="myoder";
	char PASSWORD[]="yoda";
	mysqlpp::Connection myconn(DB, HOST, USER, PASSWORD);
	mysqlpp::Query myquery=myconn.query();
	//mysqlpp::Result res1;
	mysqlpp::StoreQueryResult res1;
	int intKey;
	unsigned int fcounts[xmax*ymax];
		for (unsigned int i=0; i<xmax*ymax; i++) {
			fcounts[i]=0;
			};
	if (doSQL==1 or doSQL==5 or doSQL==25) {	
		//
		// insert a new row for this sim-run:
		myquery.reset();
		printf("insert simprams.\n");
		myquery << "insert into ForestFire.SimPrams (`SimName`, `xmax`, `ymax`, `sparkInterval`, `burnAge`, `tmax`, `nRand`, `pImmune`, `kImmune`, `Comment`) values (%0q, %1q, %2q, %3q, %4q, %5q, %6q, %7q, %8q, %9q )";
		myquery.parse();
		// note: simIndex(auto-int) and dtTime (default TIMESTAMP) set automatically.
		//myquery.execute(simName.c_str(), simName.c_str(), xmax, ymax, fmatch, burnAge, tmax, randPlant, clustPlant, kmax, simPramComment.c_str());
		  myquery.execute(simName.c_str(), xmax, ymax, fmatch, 1, tmax, 1, pImmune, kImmune, simPramComment.c_str());
		//
		// now, get the integer key for this simulation:
		// note that this could be accomplished with one call (optimal if MySQL calls have high overhead)
		// by writing a SPROC on the MySQL side.
		// also see the mysql_insert_id() (C API) and LAST_INSERT_ID() (SQL) functions, by which we should be ablt to automatically retrieve the indexID.
		myquery.reset();
		printf("fetch simIndex.\n");
		myquery << "select max(simIndex) from ForestFire.SimPrams";
		myquery.parse();
		res1 = myquery.store(simName.c_str(), simName.c_str());
		intKey = res1.at(0).at(0);
		}; // doSQL
	//
	//printf("beginnn.\n");
	for (unsigned int i=0; i<=tmax; i++) {
		// here, i'm being sloppy with random numbers. really, we need four independent
		// random number generators for xTree, yTree, xMatch, yMatch
		// printf(" iteration %d\n", i);
		//
		//
		//if (doSQL==5 or doSQL==6) if(i%1000000 == 0) printf("%d million\n", i/1000000);
		if (doSQL==6) if(i%1000000 == 0) printf("%d million\n", i/1000000);

		if (doSQL==16) {
			if(i%100000 == 0) {
				// printf("%d million\n", i/1000000);
				aveRho=0;
				aveVol=0;
				for (unsigned int k=0; k<(xmax+2)*(ymax+2); k++) {
					if (*(grids+k)>0 and *(grids+k)<rockAge) {
						aveRho = aveRho + 1;
						aveVol = aveVol + *(grids+k);
						};
					};
				//printf("mils,\t Rho,\t Vol,\t %d, %f, %f\n", i/1000000, float(aveRho)/float(xmax*ymax), float(aveVol)/float(xmax*ymax));
				printf("%d, %f, %f\n", i/1000000, float(aveRho)/float(xmax*ymax), float(aveVol)/float(xmax*ymax));
				};
			};


		//
		// PLANT A TREE:
		// select a grid for tree planting:
			//thisX = rand()%xmax+1;
			//thisY = rand()%ymax+1;
			//thisSquare = &grids[0] + thisX + (xmax+2)*thisY;	// point to the current square...
			// for speed, select one random number; if we land on a rock, then just skip. there aren't many rocks.
			thisXY = xmax+3 + rand()%((xmax+2)*ymax-1);
			thisSquare = grids + thisXY;
			// if (*thisSquare<rockAge) {
			if (*thisSquare==0) {
				*thisSquare = *thisSquare + 1;
				nTreesOnGrid ++;
				};

	// we've planted a tree. do we throw a match?
		// we can do this two ways. we can trow a match every M steps or set a 
		// 1/M probability every time.
		// for now, we're being super simple; throw a match every 'fmatch' steps:
		// throw a match with 1/fmatch probability. generate a random number beteen 1 and fmatch; each number appears with freq. 1/fmatch
		//ffmatch = float(i+1)/float(fmatch);
		//if (float(int(ffmatch))==ffmatch and i>xmax) {
		//if (rand()%((1+prefPlant)*fmatch)==1) {
		
		if (rand()%fmatch==1) {
			//yodapause();
			// throw a match.
			xFire = rand()%xmax+1;
			yFire = rand()%ymax+1;
			fireSquare = &grids[0] + xFire + (xmax+2)*yFire;
			//printf("match: (%d, %d) :: %d\n", xFire, yFire, *fireSquare);
			//yodapause();
			//
			//if (getGridStatus(*fireSquare, i) >= burnAge and getGridStatus(*fireSquare, i) < rockAge) {
			if (*fireSquare >= burnAge and *fireSquare < rockAge) {				
				// initiate a new fire.
				// start from the epicenter and work out in concentric rectangles (squares)
				// until there are no new fires.
				// note: we make two passes over each circle. for now, we assume all squares
				// continue to burn until the fire is over. this is a subtle consideration that
				// will not matter for simpler versions of the model, but if we introduce burn probabilities,
				// we will have to be more careful.
				// alternatively, we can scan the entire grid every time, but the above method will
				// save CPU time.
				//*fireSquare=-1;	// the fire-square starts burning
				*fireSquare=-(*fireSquare);	// the fire-square starts burning
				//
				rFire = 1;
				//nBurning = 1;
				dnBurning = 1;
				nBurning = dnBurning;
				//
				int yFireMin = int(yodacode::greaterOf((yFire-rFire), 1));	// we always start with a 1 squar boundary. we might, however, encounter the edges.
				int yFireMax = int(yodacode::lesserOf((yFire+rFire), float(ymax)));
				int xFireMin = int(yodacode::greaterOf(float(xFire-rFire), 1));
				int xFireMax = int(yodacode::lesserOf(float(xFire+rFire), float(xmax)));
				//printf("fire range: %d, %d, %d, %d\n", yFireMin, yFireMax, xFireMin, xFireMax);
				//printf("preplot\n.");
				//
				//plotGrid(&grids[0],i, xmax, ymax);
				if (doSQL==0) {
					printGrid(&grids[0], i, xmax, ymax);
					};
				//while (dnBurning > 0) {
				doQuench = 0;
				nFireSteps=0;	// steps fire has propagated, max dist/radius from flash-point. effectively time it's been burning.
				while (dnBurning > 0 and doQuench==0) {
					dnBurning=0;
					nFireSteps++;
					// 30 june 2008 yoder:
					//for (char doTwice = 0; doTwice <=1; doTwice++) {	// "char" is a 1 byte integer. we could also use a boolean to count to 2.
					for (char doTwice = 0; doTwice <1; doTwice++) {	// retrospectively, we don't need to do two loops since we do the whole area. also, this creates
																					// inconsistency when evaluating immunity.
																					// note: 5c data before 30 june uses the "doTwice" algorithm. different immunity effect?
					for (int iy = (yFireMin); iy <= (yFireMax); iy++) {
						//if (doQuench==1) break;
						for (int ix = (xFireMin); ix <= (xFireMax); ix++) {
							//if (doQuench==1) break;	// this is a safety measure. the loop should be otherwise killed by setting ix>xFireMax
							//
							// note this loops down then across...
							// if a neighbor is burning and the element is old enough and the element is not alread burning
							// (note by using burning -> -Age
							// also note: Gelb is right. a recursive approach is better.
							// printf("try-burn: %d, %d\n", ix, iy);
							//plotGrid(&grids[0], xmax, ymax);
							randImmune = rand()%1000;
							frandImmune = float(randImmune)/1000;
							//printf("frandImmune: %f\n", frandImmune);
							//yodapause();
							//
							int * centerGrid = &grids[0] + ix + (xmax+2)*iy;
							//
							int cStat, uStat, dStat, lStat, rStat;
						//	int ulStat, urStat, llStat, lrStat;	// diagonal elements.
						//	cStat = getGridStatus(*(centerGrid), i);
							//
						//	uStat = getGridStatus(*(centerGrid + (xmax+2)), i);
						//	dStat = getGridStatus(*(centerGrid - (xmax+2)), i);
						//	lStat = getGridStatus(*(centerGrid - 1), i);
						//	rStat = getGridStatus(*(centerGrid + 1), i);
						//	cStat = getGridStatus(*(centerGrid), i);
							//
							cStat = *(centerGrid);
							//
							uStat = *(centerGrid + (xmax+2));
							dStat = *(centerGrid - (xmax+2));
							lStat = *(centerGrid - 1);
							rStat = *(centerGrid + 1);
							//
							// diagonal elements:
						//	ulStat = getGridStatus(*(centerGrid + (xmax+2) - 1), i);
						//	urStat = getGridStatus(*(centerGrid + (xmax+2) + 1), i);
						//	llStat = getGridStatus(*(centerGrid - (xmax+2) - 1), i);
						//	lrStat = getGridStatus(*(centerGrid - (xmax+2) + 1), i);
							//yodapause();
							//if (grids[iy][ix] >= burnAge && (grids[ix+1][iy]==-1 || grids[ix-1][iy]==-1 || grids[ix][iy+1]==-1 || grids[ix][iy-1]==-1) ) {
							//printf(" checking: cg=%d, lg=%d, rg=%d, ug=%d, dg=%d, anyburn=%d\n", *centerGrid, *leftGrid, *rightGrid, *upGrid, *downGrid, (*leftGrid==-1 or *rightGrid==-1 or *upGrid==-1 or *downGrid==-1) );
							//if (*centerGrid >= burnAge and (*leftGrid==-1 or *rightGrid==-1 or *upGrid==-1 or *downGrid==-1)) {
							//if (*centerGrid >= burnAge and (*leftGrid<=-burnPropAge or *rightGrid<=-burnPropAge or *upGrid<=-burnPropAge or *downGrid<=-burnPropAge)) {
							//if (cStat >= burnAge and cStat < rockAge and (lStat<=-burnPropAge or rStat<=-burnPropAge or uStat<=-burnPropAge or dStat<=-burnPropAge)) {
							//
							// no immunity:
							//if (cStat >= burnAge and cStat < rockAge and (lStat<=-burnPropAge or rStat<=-burnPropAge or uStat<=-burnPropAge or dStat<=-burnPropAge)) {
							// local immunity:
							//printf("immune factor: %f, %f\n", pImmune, frandImmune);
							//if (frandImmune > pImmune and cStat >= burnAge and cStat < rockAge and (lStat<=-burnPropAge or rStat<=-burnPropAge or uStat<=-burnPropAge or dStat<=-burnPropAge)) {
							// next nearest neighbors:
							/*	
							if (cStat >= burnAge and cStat < rockAge 
								and  ( (lStat<=-burnPropAge or rStat<=-burnPropAge or uStat<=-burnPropAge or dStat<=-burnPropAge)
									 or ( (ulStat<=-nnnAge or urStat<=-nnnAge  or llStat<=-nnnAge  or lrStat<=-nnnAge)
										 and (ulStat<=-burnPropAge or urStat<=-burnPropAge or llStat<=-burnPropAge  or lrStat<=-burnPropAge)
										 )
							 		)
								) {
							*/
							if (cStat >= burnAge and cStat < rockAge 
								and (lStat<=-burnPropAge or rStat<=-burnPropAge or uStat<=-burnPropAge or dStat<=-burnPropAge)
								and frandImmune>(pImmune/float(nBurning+dnBurning))) {
								// 5c1: we've added element level f(k) immunity to each element; no quenching.
								*centerGrid = -(*centerGrid);
								// age -> number of trees in that grid...
								dnBurning ++;
								//
								// 5c1: no quenching. immunity evaluated on an element-by-element basis above.
								// what if we evaluate immunity here? if quench, break the propagation loop. (can we break-break? how 'bout we just set the iterators over the max vals):
								// note: we've not yet updated nBurning, so use nBurning + dnBurning:
								//if (frandImmune < (pImmune/(1+(float(nBurning+dnBurning)/kImmune))) ) {
							//	if (frandImmune < (pImmune/float(nBurning+dnBurning)) ) {
							//		// this seems to give us some funny log-periodic behavior for small Pimmune.
							//		// the next thing to try is: evaluate Pquench as each element is burned, but mitigate the introduction of new geometry (aka, the loop around the fire) by,
							//		// when frandImmune fails (fire quenches), we set doQuench=1, but let the fire continue through its current perimeter. maybe we need to just start testing
							//		// each individual element for burn?
							//		doQuench=1;
							//		ix=xFireMax+1;
							//		iy=yFireMax+1;
							//		};
								// printf("[%d, %d] catches from [%d, %d]\n", ix, iy, xFire, yFire);
								};
							}; // ix
						}; // iy
						}; // doTwice	
						nBurning = nBurning + dnBurning;
						//
						// mean-field immunities:
						// normalize formulae to extinguish size1 fires with probability pImmune
						//
						// inverse linear type (becareful of x/0):
						// if (frandImmune < (1+(1/kImmune))*(pImmune/(1+(float(nBurning)/kImmune))) ) {
						// if (frandImmune < pImmune/(1+(float(nBurning-1)/kImmune)) ) {
						// exponential:
						// if (frandImmune < pImmune*exp(-kImmune*(nBurning-1)) ) doQuench=1;
						// power law:
						// if (frandImmune < pImmune*pow(nBurning, -kImmune)) {
						//printf("kImmune norm: 1 + (1/kImmune): %f\n", 1 + (1/kImmune));
						//
				////////////////////////
				// temporarily move immunity inside the prop-loop.		
						// IMMUNITY (note different functions we play with):
						// do we quenche the fire?
						// 1/nFireSteps:
						//if (frandImmune < (pImmune/nFireSteps) ) {		// this is dumb way to make this work. stick to k
						// omori-type:
				//		if (frandImmune < (pImmune/(1+(float(nBurning-1)/kImmune))) ) {
				//		// pure 1/k:
				//		//if (frandImmune < (pImmune*kImmune/nBurning) ) {
				//		//if (frandImmune < pow(pImmune,(float(nBurning)/5) )) {
				//			doQuench=1;
				//			//printf("quenched %d.\n", nBurning);
				//			//yodapause();
				//			};
				/////////////////////////
					//rFire++;
					xFireMin = int(yodacode::greaterOf(1, float(xFireMin-1)));
					xFireMax = int(yodacode::lesserOf(float(xmax), xFireMax+1));
					yFireMin = int(yodacode::greaterOf(1, float(yFireMin-1)));
					yFireMax = int(yodacode::lesserOf(float(ymax), yFireMax+1));
					// g1.plot_xy(vfireX, vfireY, "");
					};	// end fire still burining
				//
				// recursive method:
				// if (grids[xFire][yFire] >= burnAge) {
				//	burn(xFire, yFire);	// burn() will look up, down, right, left and call itself recursively. we have to do the "pass array address" bit though...
				//	};
				//
				nFires++;
				nBurnedTotal = nBurnedTotal + nBurning;
				nTreesOnGrid = nTreesOnGrid-nBurning;
				fcounts[nBurning-1]++;
			//	plotGrid(&grids[0], xmax, ymax);
				if (doSQL==0) {
					printGrid(&grids[0], i, xmax, ymax);
					};
				// write fire to MySQL:
				if (doSQL==1) {
					// printf("fire size, nFires, totalBurned: (%d) (%d) (%d)\n", nBurning, nFires, nBurnedTotal);
					myquery.reset();
					myquery << "insert into ForestFire.ForestFires (simIndex, t, xSpark, ySpark, nBurned, nTrees) values (%0q, %1q, %2q, %3q, %4q, %5q) ";
					myquery.parse();
					myquery.execute(intKey, i, xFire, yFire, nBurning, nTreesOnGrid);
					//yodapause();
					};
				if (doSQL==3) {
					printf("fire at time %d\n", i);
					if (nBurning>=xmax/5) plotGrid (&grids[0], i, xmax, ymax, burnPropAge);
					};
				if (doSQL==4) {
					if (nBurning>=xmax/5) plotGridImg (&grids[0], i, xmax, ymax, burnPropAge);
					};
				//
				// fires finished burning; extinguish:
				for (int iy = (yFireMin); iy <= (yFireMax); iy++) {
					for (int ix = (xFireMin); ix <= (xFireMax); ix++) {
						// &grids[0] + ix + (xmax+2)*iy
						if (grids[ix + (xmax+2)*iy] < 0) grids[ix + (xmax+2)*iy]=0;
						};
					};
				}; //else printf("no tree at match point.\n");	// if match -> tree...
			}; // if match-time

		// do we initialize with 0?
		//printf("ary element 0,i: %d", grids[0][i]);
		};	// end sim-steps.

	// end simulation.
	//printf("doSQL: %d\n", doSQL);
	// doSQL's:
	// 0: 'print-grid" fires
	// 1: full SQL: insert each forest fire data-set into ForestFires
	// 2: print summary to screen. use this for direct gnuplot calls, " plot '<./ffire4...'" 
	// 3: Print each fire to screen; "plotGrid" each fire nBurning>(25) print summary to screen at end
	// 4: plotGridImg each fire nBurning>(20); print summary to screen,
	// 5: SQL: insert just summary data to SQL; prints progress by million (will screw up plotting)
	// 6: report summary, progress by million.
	// 11: return to standard-output the last grid in full. use to make an image of the final grid.
	//
	// for super long runs (10^9 steps), it looks like the mysql connection times out, so all is lost.
	// renew the connection. 
	//
//	if (myconn.connected()==0) myconn.connect(DB, HOST, USER, PASSWORD);
	mysqlpp::Connection newconn(DB, HOST, USER, PASSWORD);
	mysqlpp::Query newquery=myconn.query();
	//mysqlpp::Result res1;

	//mysqlpp::Query myquery=myconn.query();
	//mysqlpp::Result res1;
	// end-o-run summaries (print):
	if (doSQL==2  or doSQL==25 or doSQL==3 or doSQL==4 or doSQL==6) {
		for (unsigned int i=0; i<(xmax*ymax); i++) {
			if (fcounts[i]!=0) printf("%d\t%d\n", i+1, fcounts[i]);
			//printf("%d,\t%d\n", i+1, fcounts[i]);
			};
		} else {
			//printf("finished.\nfire size, nFires, totalBurned: (%d) (%d) (%d)\n", nBurning, nFires, nBurnedTotal);
			};
	if (doSQL==5 or doSQL==25 ) { // no plots, just a summary -> SQL
		//
		for (unsigned int i=0; i<(xmax*ymax); i++) {
			// if (fcounts[i]!=0) printf("%d\t%d\n", i+1, fcounts[i]);
		//	printf ("sql bits: %d, %d, %d, %d\n", intKey, tmax, i+1, fcounts[i]);
			newquery.reset();
			newquery << "insert into ffcounts (simIndex, tmax, nBurned, nEvents) values (%0q, %1q, %2q, %3q)";
			newquery.parse();
			newquery.execute(intKey, tmax, i+1, fcounts[i]);
			//printf("%d,\t%d\n", i+1, fcounts[i]);
			};				
		};
	// return the final grid in full and give an average density at the end...?
	if (doSQL==11) {
		for (unsigned int i=0; i<(xmax+2)*(ymax+2); i++) {
			printf ("%d,\t%d,\t%d\n", i-int(i/(xmax+2))*(xmax+2), i/(xmax+2), getGridStatus(*(grids+i), tmax));
			};
		};
	//g1.reset_plot();
	//g1.plot_xyz(vx, vy, vGridStat, "xyz plot of TreesPlanted");

	//yodacode::yodapause();
	return 0;
	//return &grids[0];
	};
Esempio n. 3
0
void MapView::Render()
{

	// get new pose.
	pthread_mutex_lock(&filter->filter_CS);
	lastFramePoseSpeed = filter->getCurrentPoseSpeedAsVec();	// Note: this is maybe an old pose, but max. one frame old = 50ms = not noticable.
	pthread_mutex_unlock(&filter->filter_CS);

	


	if(clearTrail)
	{
		trailPoints.clear();
		clearTrail = false;
	}

	// render
	bool addTrail;
	if(trailPoints.size() == 0)
		addTrail = true;
	else
	{
		TooN::Vector<3> distToLast = lastFramePoseSpeed.slice<0,3>() - trailPoints[trailPoints.size()-1].pointFilter;
		double d = distToLast[0]*distToLast[0] + distToLast[1]*distToLast[1]+distToLast[2]*distToLast[2];
		addTrail = d > 0.1*0.1;
	}


	


	// the following complicated code is to save trail-points in ptam-scale, such that scale-reestimation will re-scale the drawn path.
	if(addTrail)
	{
		if(ptamWrapper->PTAMStatus == ptamWrapper->PTAM_BEST ||
				ptamWrapper->PTAMStatus == ptamWrapper->PTAM_TOOKKF ||
				ptamWrapper->PTAMStatus == ptamWrapper->PTAM_GOOD)
		{
			if(ptamWrapper->PTAMInitializedClock != 0 && getMS() - ptamWrapper->PTAMInitializedClock > 200)
			{
				TooN::Vector<3> PTAMScales = filter->getCurrentScales();
				TooN::Vector<3> PTAMOffsets = filter->getCurrentOffsets().slice<0,3>();

				TooN::Vector<3> ptamPointPos = lastFramePoseSpeed.slice<0,3>();
				ptamPointPos -= PTAMOffsets;
				ptamPointPos /= PTAMScales[0];

				trailPoints.push_back(TrailPoint(
					lastFramePoseSpeed.slice<0,3>(),
					ptamPointPos
				));
			}
		}
		else if(ptamWrapper->PTAMStatus == ptamWrapper->PTAM_LOST ||
				ptamWrapper->PTAMStatus == ptamWrapper->PTAM_FALSEPOSITIVE)
		{
			if(ptamWrapper->PTAMInitializedClock != 0 && getMS() - ptamWrapper->PTAMInitializedClock > 200)
			{
				TooN::Vector<3> PTAMScales = filter->getCurrentScales();
				TooN::Vector<3> PTAMOffsets = filter->getCurrentOffsets().slice<0,3>();

				TooN::Vector<3> ptamPointPos = lastFramePoseSpeed.slice<0,3>();
				ptamPointPos -= PTAMOffsets;
				ptamPointPos /= PTAMScales[0];

				trailPoints.push_back(TrailPoint(
					lastFramePoseSpeed.slice<0,3>(),
					ptamPointPos
				));
			}
		}
		else
		{
			trailPoints.push_back(TrailPoint(
				lastFramePoseSpeed.slice<0,3>()
			));
		}
	}





	if(resetMapViewFlag)
	{
		resetMapView();
		resetMapViewFlag = false;
	}

	// get lineWidthFactor
	lineWidthFactor = sqrt((float)(myGLWindow->size()[0] * myGLWindow->size()[1] / (640*480)));



	plotGrid();

	pthread_mutex_lock(&ptamWrapper->shallowMapCS);
	std::vector<tse3>* kfl = &(ptamWrapper->keyFramesTransformed);
	
	// draw keyframes
	for(unsigned int i=0;i<kfl->size();i++)
	{
		plotCam((*kfl)[i],false,2,0.04f,1);
	}
	
	// draw trail
	drawTrail();

	// draw keypoints
	plotMapPoints();
	pthread_mutex_unlock(&ptamWrapper->shallowMapCS);

	// draw predicted cam


	// real in opaque
	predConvert->setPosRPY(lastFramePoseSpeed[0], lastFramePoseSpeed[1], lastFramePoseSpeed[2], lastFramePoseSpeed[3], lastFramePoseSpeed[4], lastFramePoseSpeed[5]);
	plotCam(predConvert->droneToGlobal,true,5.0f,0.2f,1);


	// --------------------- make msg ------------------------------
	msg = "";
	TooN::Vector<6> of = filter->getCurrentOffsets();
	TooN::Vector<3> sc = filter->getCurrentScales();


	if(drawUI == UI_DEBUG)
	{
		snprintf(charBuf,1000,"Pose:              ");
		snprintf(charBuf+10,800, "x: %.2f                          ",lastFramePoseSpeed[0]);
		snprintf(charBuf+20,800, "y: %.2f                          ",lastFramePoseSpeed[1]);
		snprintf(charBuf+30,800, "z: %.2f                          ",lastFramePoseSpeed[2]);
		snprintf(charBuf+40,800, "r: %.2f                          ",lastFramePoseSpeed[3]);
		snprintf(charBuf+50,800, "p: %.2f                          ",lastFramePoseSpeed[4]);
		snprintf(charBuf+60,800, "y: %.2f                          ",lastFramePoseSpeed[5]);
		snprintf(charBuf+70,800, "vx: %.2f                          ",lastFramePoseSpeed[6]);
		snprintf(charBuf+80,800, "vy: %.2f                          ",lastFramePoseSpeed[7]);
		snprintf(charBuf+90,800, "vz: %.2f                          ",lastFramePoseSpeed[8]);
		snprintf(charBuf+100,800, "vy: %.2f",lastFramePoseSpeed[9]);
		msg += charBuf;
	

		snprintf(charBuf,1000,"\nSync:              ");
		snprintf(charBuf+10,800, "ox: %.2f                          ",of[0]);
		snprintf(charBuf+20,800, "oy: %.2f                          ",of[1]);
		snprintf(charBuf+30,800, "oz: %.2f                          ",of[2]);
		snprintf(charBuf+40,800, "or: %.2f                          ",of[3]);
		snprintf(charBuf+50,800, "op: %.2f                          ",of[4]);
		snprintf(charBuf+60,800, "oy: %.2f                          ",of[5]);
		snprintf(charBuf+70,800, "Sx: %.2f                          ",sc[0]);
		snprintf(charBuf+80,800, "Sy: %.2f                          ",sc[1]);
		snprintf(charBuf+90,800, "Sz: %.2f",sc[2]);
		msg += charBuf;


		snprintf(charBuf,1000,"\nStDvs:                 ");
		snprintf(charBuf+10,800, "x: %.2f                          ",std::sqrt((double)lastFramePoseSpeed[0]));
		snprintf(charBuf+20,800, "y: %.2f                          ",std::sqrt((double)lastFramePoseSpeed[1]));
		snprintf(charBuf+30,800, "z: %.2f                          ",std::sqrt((double)lastFramePoseSpeed[2]));
		snprintf(charBuf+40,800, "r: %.2f                          ",std::sqrt((double)lastFramePoseSpeed[3]));
		snprintf(charBuf+50,800, "p: %.2f                          ",std::sqrt((double)lastFramePoseSpeed[4]));
		snprintf(charBuf+60,800, "y: %.2f                          ",std::sqrt((double)lastFramePoseSpeed[5]));
		snprintf(charBuf+70,800, "vx: %.2f                          ",std::sqrt((double)lastFramePoseSpeed[6]));
		snprintf(charBuf+80,800, "vy: %.2f                          ",std::sqrt((double)lastFramePoseSpeed[7]));
		snprintf(charBuf+90,800, "vz: %.2f                          ",std::sqrt((double)lastFramePoseSpeed[8]));
		snprintf(charBuf+100,800, "vy: %.2f",std::sqrt((double)lastFramePoseSpeed[9]));
		msg += charBuf;
	}
	else
	{
		snprintf(charBuf,1000,"Drone Pose:             ");
		snprintf(charBuf+13,800, "xyz=(%.2f,                          ",lastFramePoseSpeed[0]);
		snprintf(charBuf+25,800, "%.2f,                          ",lastFramePoseSpeed[1]);
		snprintf(charBuf+32,800, "%.2f),                      ",lastFramePoseSpeed[2]);
		snprintf(charBuf+42,800, "rpy=(%.2f,                 ",lastFramePoseSpeed[3]);
		snprintf(charBuf+54,800, "%.2f,                          ",lastFramePoseSpeed[4]);
		snprintf(charBuf+61,800, "%.2f)                          ",lastFramePoseSpeed[5]);
		msg += charBuf;
	}
	

	myGLWindow->GetMousePoseUpdate();



	CVD::glSetFont("sans");
	if(drawUI != UI_NONE)
		myGLWindow->DrawCaption(msg);

	if(drawUI == UI_DEBUG)
	{
	  glMatrixMode(GL_PROJECTION);
	  glPushMatrix();
	  glTranslatef((float)0, (float)100, 0.0);
	  glScalef(45,-45,1);
	  snprintf(charBuf,1000,"xyz: %.2f %.2f %.2f",lastFramePoseSpeed[0],lastFramePoseSpeed[1],lastFramePoseSpeed[2]);
	  CVD::glDrawText(charBuf, CVD::NICE, 1.6, 0.1);
	  glPopMatrix();
	}
	myGLWindow->swap_buffers();
	myGLWindow->HandlePendingEvents();

}
void SPScatterPlotter::plot(QPainter &painter, QRect area) const
{
    plotGrid(painter, area);
    plotAxis(painter, area, m_xlabel, m_ylable);
    plotData(painter, area);
}