Index: /cpp/frams/_demos/evol_test.cpp
===================================================================
--- /cpp/frams/_demos/evol_test.cpp	(revision 1030)
+++ /cpp/frams/_demos/evol_test.cpp	(revision 1031)
@@ -10,4 +10,5 @@
 #include "frams/genetics/genman.h"
 #include "frams/model/model.h"
+#include "frams/model/geometry/modelgeometryinfo.h"
 
 
@@ -25,41 +26,72 @@
 double get_fitness(const Individual &ind, const char *fitness_def)
 {
+	const double GEOM_DENSITY = 5.0; //needs testing and adjusting as needed - tradeoff between precision and speed
+
 	SString genotype = ind.geno.getGenes();
 	Model model = Model(ind.geno, Model::SHAPETYPE_UNKNOWN);
 	double fitness = 0;
 	const char *p = fitness_def;
+
+	Orient axes;
+	Pt3D sizes;
 	while (*p)
 	{
 		switch (*p)
 		{
-		case '0':
-			break;
-		case '!': //special symbol for current fitness (used only in printing population stats)
-			fitness += ind.fitness;
-			break;
-		case 'l':
-		case 'L':
-			fitness += criterion(*p, genotype.length());
-			break;
-		case 'p':
-		case 'P':
-			fitness += criterion(*p, model.getPartCount());
-			break;
-		case 'j':
-		case 'J':
-			fitness += criterion(*p, model.getJointCount());
-			break;
-		case 'n':
-		case 'N':
-			fitness += criterion(*p, model.getNeuroCount());
-			break;
-		case 'c':
-		case 'C':
-			fitness += criterion(*p, model.getConnectionCount());
-			break;
-			// TODO add more criteria as described in main() below
-		default:
-			printf("Unknown fitness criterion symbol: '%c'\n", *p);
-			exit(3);
+			case '0':
+				break;
+			case '!': //special symbol for current fitness (used only in printing population stats)
+				fitness += ind.fitness;
+				break;
+			case 'g':
+			case 'G':
+				fitness += criterion(*p, genotype.length());
+				break;
+			case 'p':
+			case 'P':
+				fitness += criterion(*p, model.getPartCount());
+				break;
+			case 'j':
+			case 'J':
+				fitness += criterion(*p, model.getJointCount());
+				break;
+			case 'n':
+			case 'N':
+				fitness += criterion(*p, model.getNeuroCount());
+				break;
+			case 'c':
+			case 'C':
+				fitness += criterion(*p, model.getConnectionCount());
+				break;
+			case 'b':
+			case 'B':
+				fitness += criterion(*p, model.size.x * model.size.y * model.size.z);
+				break;
+			case 's':
+			case 'S':
+				fitness += criterion(*p, ModelGeometryInfo::area(model, GEOM_DENSITY));
+				break;
+			case 'v':
+			case 'V':
+				fitness += criterion(*p, ModelGeometryInfo::volume(model, GEOM_DENSITY));
+				break;
+			case 'l':
+			case 'L':
+				ModelGeometryInfo::findSizesAndAxes(model, GEOM_DENSITY, sizes, axes);
+				fitness += criterion(*p, sizes.x);
+				break;
+			case 'w':
+			case 'W':
+				ModelGeometryInfo::findSizesAndAxes(model, GEOM_DENSITY, sizes, axes);
+				fitness += criterion(*p, sizes.y);
+				break;
+			case 'h':
+			case 'H':
+				ModelGeometryInfo::findSizesAndAxes(model, GEOM_DENSITY, sizes, axes);
+				fitness += criterion(*p, sizes.z);
+				break;
+			default:
+				printf("Unknown fitness criterion symbol: '%c'\n", *p);
+				exit(3);
 		}
 		p++;
@@ -81,6 +113,6 @@
 		criterion_values.push_back(get_fitness(ind, crit));
 	printf("%g,%g,%g", *std::min_element(criterion_values.begin(), criterion_values.end()),
-		std::accumulate(criterion_values.begin(), criterion_values.end(), 0.0) / criterion_values.size(),
-		*std::max_element(criterion_values.begin(), criterion_values.end()));
+		   std::accumulate(criterion_values.begin(), criterion_values.end(), 0.0) / criterion_values.size(),
+		   *std::max_element(criterion_values.begin(), criterion_values.end()));
 }
 
@@ -120,10 +152,15 @@
 		printf("Each letter corresponds to one fitness criterion, and they are all weighted and added together.\n");
 		printf("  0      - a constant value of 0 that provides a flat fitness landscape (e.g. for testing biases of genetic operators).\n");
-		printf("  l or L - genotype length in characters.\n");
-		printf("  p or P - the number of Parts.\n");
-		printf("  j or J - the number of Joints.\n");
-		printf("  n or N - the number of Neurons.\n");
-		printf("  c or C - the number of neural Connections.\n");
-		//TODO add b - bounding box volume (from Model), s - surface area (from geometry), v - volume (from geometry), h,w,d - three consecutive dimensions (from geometry)
+		printf("  g or G - genotype length in characters.\n");
+		printf("  p or P - number of Parts.\n");
+		printf("  j or J - number of Joints.\n");
+		printf("  n or N - number of Neurons.\n");
+		printf("  c or C - number of neural Connections.\n");
+		printf("  b or B - volume of the bounding box (absolute coordinates).\n");
+		printf("  s or S - surface area of the Model.\n");
+		printf("  v or V - volume of the Model.\n");
+		printf("  l or L - length of the Model (largest dimension).\n");
+		printf("  w or W - width of the Model (2nd largest dimension).\n");
+		printf("  h or H - height of the Model (smallest dimension).\n");
 
 		printf("\nThe output consists of 7 columns separated by the TAB character.\n");
@@ -193,5 +230,5 @@
 		{
 			printf("Evaluation %d", i);
-			for (char c : string("!PJNCL"))
+			for (char c : string("!PJNCG"))
 			{
 				printf("\t");
