Index: /trunk/VUT/GtpVisibilityPreprocessor/include/Polygon3.h
===================================================================
--- /trunk/VUT/GtpVisibilityPreprocessor/include/Polygon3.h	(revision 235)
+++ /trunk/VUT/GtpVisibilityPreprocessor/include/Polygon3.h	(revision 238)
@@ -48,5 +48,5 @@
 	/** Deletes all polygons om the queue.
 	*/
-	static void DeletePolygons(PolygonQueue *polys);
+	static void DeletePolygons(PolygonContainer *polys);
 
 	/// vertices are connected in counterclockwise order.
Index: /trunk/VUT/GtpVisibilityPreprocessor/scripts/default.env
===================================================================
--- /trunk/VUT/GtpVisibilityPreprocessor/scripts/default.env	(revision 237)
+++ /trunk/VUT/GtpVisibilityPreprocessor/scripts/default.env	(revision 238)
@@ -60,7 +60,10 @@
 BspTree {
 #	splitPlaneStrategy leastSplits
-	splitPlaneStrategy nextPolygon
+	splitPlaneStrategy balancedTree
+#	splitPlaneStrategy nextPolygon
 #	constructionMethod viewCells
 	constructionMethod sceneGeometry
+	maxCandidates 20
+	maxViewCells 100
 	Termination {
 		maxPolygons 4
Index: /trunk/VUT/GtpVisibilityPreprocessor/src/Polygon3.h
===================================================================
--- /trunk/VUT/GtpVisibilityPreprocessor/src/Polygon3.h	(revision 237)
+++ /trunk/VUT/GtpVisibilityPreprocessor/src/Polygon3.h	(revision 238)
@@ -13,8 +13,7 @@
 class Face;
 
-
-/** Queue storing a soup of polygons used during BSP tree construction
+/** Container storing polygons used during BSP tree construction
 */
-typedef queue<Polygon3 *> PolygonQueue;
+typedef vector<Polygon3 *> PolygonContainer;
 
 /** Class representing a general planar polygon in 3d.
@@ -32,5 +31,5 @@
 	/** Returns supporting plane of this polygon.
 	*/
-	Plane3 GetSupportingPlane();
+	Plane3 GetSupportingPlane() const;
 
 	/** Splits polygon.
@@ -44,12 +43,17 @@
 	enum {BACK_SIDE, FRONT_SIDE, SPLIT, COINCIDENT};
 
-	/** Side of the plane where the polygon is located.
+	/** Classify polygon with respect to the plane.
 	    @returns one of BACK_SIDE, FRONT_SIDE, SPLIT, COINCIDENT
 	*/
-	int Side(Plane3 *plane);
+	int ClassifyPlane(const Plane3 &plane) const;
+
+	/** Side of the polygon with respect to the plane.
+		@returns 1 if on front side, -1 if on back side, 0 else.
+	*/
+	int Side(const Plane3 &plane) const;
 
 	/** Deletes all polygons om the queue.
 	*/
-	static void DeletePolygons(PolygonQueue *polys);
+	static void DeletePolygons(PolygonContainer *polys);
 
 	/// vertices are connected in counterclockwise order.
Index: /trunk/VUT/GtpVisibilityPreprocessor/src/ViewCellBsp.h
===================================================================
--- /trunk/VUT/GtpVisibilityPreprocessor/src/ViewCellBsp.h	(revision 237)
+++ /trunk/VUT/GtpVisibilityPreprocessor/src/ViewCellBsp.h	(revision 238)
@@ -16,7 +16,7 @@
 class Polygon3;
 
-/** Queue storing a soup of polygons used during BSP tree construction
+/** Container storing a soup of polygons used during BSP tree construction
 */
-typedef std::queue<Polygon3 *> PolygonQueue;
+typedef std::vector<Polygon3 *> PolygonContainer;
 
 class BspTreeStatistics // TODO: should have common superclass with KdTreeStatistics
@@ -143,5 +143,6 @@
 		@param splits number of splits
 	*/
-	void SplitPolygons(PolygonQueue *polys, PolygonQueue *frontPolys, PolygonQueue *backPolys, int &splits);
+	void SplitPolygons(PolygonContainer *polys, PolygonContainer *frontPolys, 
+					   PolygonContainer *backPolys, int &splits);
 
 	friend ostream &operator<<(ostream &s, const BspInterior &A)
@@ -194,5 +195,5 @@
 		BspInterior *mParent;
 		/// polygonal data for splitting
-		PolygonQueue *mPolygons;
+		PolygonContainer *mPolygons;
 		/// current depth
 		int mDepth;
@@ -200,5 +201,5 @@
 		BspTraversalData() {}
 		
-		BspTraversalData(BspNode *node, BspInterior *parent, PolygonQueue *polys, const int depth): 
+		BspTraversalData(BspNode *node, BspInterior *parent, PolygonContainer *polys, const int depth): 
 		mNode(node), mParent(parent), mPolygons(polys), mDepth(depth) {}
     };
@@ -231,4 +232,20 @@
 
 protected:
+	
+	/** Evaluates plane classification with respect to the plane's 
+		contribution for a balanced tree.
+	*/
+	static inline int EvalForBalancedTree(const int classficiation);
+	/** Evaluates plane classification with respect to the plane's 
+		contribution for a minimum number splits in the tree.
+	*/
+	static inline int EvalForLeastSplits(const int classification);
+
+	/** Evaluates the contribution of the candidate split plane.
+	*/
+	int EvalSplitPlane(PolygonContainer *polygons, const Plane3 &candidatePlane) const;
+
+	/** Evaluates tree stats in the BSP tree leafs.
+	*/
 	void EvaluateLeafStats(const BspTraversalData &data);
 
@@ -241,7 +258,7 @@
 
 	/** Selects a splitting plane. 
-		@param polyQueue the polygon data on which the split decition is based
-	*/
-	Plane3 SelectPlane(PolygonQueue *polyQueue);
+		@param polygons the polygon data on which the split decition is based
+	*/
+	Plane3 SelectPlane(PolygonContainer *polygons) const;
 
 	/** Filters next viewcell down the tree and inserts it into the appropriate leaves
@@ -259,7 +276,7 @@
 	*/
 	BspNode *SubdivideNode(BspLeaf *leaf, BspInterior *parent, 
-							PolygonQueue *polys, const int depth, 
+							PolygonContainer *polys, const int depth, 
 							ViewCell *viewCell,
-							PolygonQueue *frontPolys, PolygonQueue *backPolys);
+							PolygonContainer *frontPolys, PolygonContainer *backPolys);
 
 	/** Filters polygons down the tree.
@@ -269,14 +286,20 @@
 		@param backPolys returns the polygons in the back of the split plane
 	*/
-	void FilterPolygons(BspInterior *node, PolygonQueue *polys, 
-						PolygonQueue *frontPolys, PolygonQueue *backPolys);
+	void FilterPolygons(BspInterior *node, PolygonContainer *polys, 
+						PolygonContainer *frontPolys, PolygonContainer *backPolys);
+
+	/** Selects the split plane in order to get a balanced tree.
+		@param polygons container of polygons
+		@param maxTests the maximal number of candidate tests
+	*/
+	Plane3 SelectPlaneHeuristics(PolygonContainer *polygons, int maxTests) const;
 
 	/** Extracts the meshes of the objects and copies them into the mesh.
 	*/
-	static void Copy2PolygonSoup(const ObjectContainer &objects, PolygonQueue &polys);
+	static void Copy2PolygonSoup(const ObjectContainer &objects, PolygonContainer &polys, int maxPolys);
 
 	/** copy this mesh into polygons.
 	*/
-	static void CopyMesh2Polygons(Mesh *mesh, PolygonQueue &polys);
+	static void CopyMesh2Polygons(Mesh *mesh, PolygonContainer &polys);
 
 	/// Pointer to the root of the tree
@@ -293,5 +316,5 @@
 
 	/// Strategies for choosing next split plane.
-	enum {NEXT_POLYGON, LEAST_SPLITS};
+	enum {NEXT_POLYGON, LEAST_SPLITS, BALANCED_TREE, COMBINED};
 
 public:
@@ -303,6 +326,8 @@
 	/// maximal possible depth
 	static int sTermMaxDepth;
-
+	/// strategy to get the best split plane
 	static int sSplitPlaneStrategy;
+	/// number of candidates evaluated for the next split plane
+	static int sMaxCandidates;
 };
 
Index: /trunk/VUT/GtpVisibilityPreprocessor/src/Environment.cpp
===================================================================
--- /trunk/VUT/GtpVisibilityPreprocessor/src/Environment.cpp	(revision 235)
+++ /trunk/VUT/GtpVisibilityPreprocessor/src/Environment.cpp	(revision 238)
@@ -1170,4 +1170,14 @@
 	  "-bsp_construction_method=",
 	  "viewCells");
+
+  RegisterOption("BspTree.maxCandidates",
+	  optInt,
+	  "-bsp_max_candidates=",
+	  "20");
+
+  RegisterOption("BspTree.maxViewCells",
+	  optInt,
+	  "-bsp_max_viewcells=",
+	  "100");
 }
 
Index: /trunk/VUT/GtpVisibilityPreprocessor/src/ViewCellBsp.cpp
===================================================================
--- /trunk/VUT/GtpVisibilityPreprocessor/src/ViewCellBsp.cpp	(revision 237)
+++ /trunk/VUT/GtpVisibilityPreprocessor/src/ViewCellBsp.cpp	(revision 238)
@@ -4,12 +4,15 @@
 #include "common.h"
 #include "ViewCell.h"
-#include <stack>
 #include "Environment.h"
 #include "Polygon3.h"
+
+#include <stack>
+#include <time.h>
+#include <iomanip>
 
 int BspTree::sTermMaxPolygons = 10;
 int BspTree::sTermMaxDepth = 20;
 int BspTree::sSplitPlaneStrategy = NEXT_POLYGON; 
-
+int BspTree::sMaxCandidates = 10;
 
 /****************************************************************/
@@ -85,18 +88,18 @@
 }
 
-void BspInterior::SplitPolygons(PolygonQueue *polys, 
-								PolygonQueue *frontPolys, 
-								PolygonQueue *backPolys, 
+void BspInterior::SplitPolygons(PolygonContainer *polys, 
+								PolygonContainer *frontPolys, 
+								PolygonContainer *backPolys, 
 								int &splits)
 {
- 	while (!polys->empty())
-	{
-		Polygon3 *poly = polys->front();
-
-		polys->pop();
+	while (!polys->empty())
+	{
+		Polygon3 *poly = polys->back();
+
+		polys->pop_back();
 
 		Debug << (*poly);
 
-		int result = poly->Side(&mPlane);
+		int result = poly->ClassifyPlane(mPlane);
 
 		Polygon3 *front_piece = NULL;
@@ -106,10 +109,13 @@
 		{
 			case Polygon3::COINCIDENT:
-				//break; //TODO: comment in
+				Debug << "coincident\n";
+				break; // do nothing
 			case Polygon3::FRONT_SIDE:
-				frontPolys->push(poly);
+				Debug << "front\n";
+				frontPolys->push_back(poly);
 				break;
 			case Polygon3::BACK_SIDE:
-				backPolys->push(poly);
+				Debug << "back\n";
+				backPolys->push_back(poly);
 				break;
 			case Polygon3::SPLIT:
@@ -117,11 +123,16 @@
 				back_piece = new Polygon3();
 
+				Debug << "\n\n**************SPLIT***************\n";
+				Debug << "Split plane: " << mPlane << "\noriginal " << (*poly) << endl;
+
 				//-- split polygon
 				poly->Split(&mPlane, front_piece, back_piece, splits);
 			
-				Debug << "SPLIT, plane: " << mPlane << "\norginal: " << (*poly) << "\nback: " << (*back_piece) << "\nfront: " << (*front_piece) << endl;
-				backPolys->push(back_piece);
-				frontPolys->push(front_piece);
-
+				Debug << "new front " << (*front_piece) << endl;
+				Debug << "new back " << (*back_piece) << endl;
+
+				frontPolys->push_back(front_piece);
+				backPolys->push_back(back_piece);
+				
 				// don't need polygon anymore
 				DEL_PTR(poly);
@@ -129,4 +140,5 @@
 				break;
 			default:
+				Debug << "SHOULD NEVER COME HERE\n";
 				break;
 		}
@@ -160,4 +172,5 @@
 {
 	mRoot = new BspLeaf();
+	Randomize(); // initialise random generator for heuristics
 }
  
@@ -170,4 +183,6 @@
 {
 	app << "===== BspTree statistics ===============\n";
+
+	app << setprecision(4);
 
 	app << "#N_RAYS Number of rays )\n"
@@ -200,6 +215,4 @@
 	objectRefs/(double)Leaves() << "\n";
 
-	//  app << setprecision(4);
-
 	app << "#N_PEMPTYLEAVES  ( Percentage of leaves with zero query domains )\n"<<
 	zeroQueryNodes*100/(double)Leaves()<<endl;
@@ -255,7 +268,8 @@
 void BspTree::InsertViewCell(ViewCell *viewCell)
 {
+	Debug << "Inserting view cells\n";
 	std::stack<BspTraversalData> tStack;
 	
-	PolygonQueue polys;
+	PolygonContainer polys;
 	// copy polygon information to guide the split process
 	CopyMesh2Polygons(viewCell->GetMesh(), polys);
@@ -275,6 +289,6 @@
 
 			// filter polygons down the tree.
-			PolygonQueue *frontPolys = new PolygonQueue();
-			PolygonQueue *backPolys = new PolygonQueue();
+			PolygonContainer *frontPolys = new PolygonContainer();
+			PolygonContainer *backPolys = new PolygonContainer();
 
 			int splits = 0;
@@ -289,5 +303,5 @@
 				delete frontPolys;
 
-			if (backPolys > 0) // if polygons on this side of bsp tree
+			if (backPolys->size() > 0) // if polygons on this side of bsp tree
 				tStack.push(BspTraversalData(interior->GetBack(), interior->GetParent(), 
 							backPolys, tData.mDepth + 1));
@@ -319,5 +333,5 @@
 }
 
-void BspTree::CopyMesh2Polygons(Mesh *mesh, PolygonQueue &polys)
+void BspTree::CopyMesh2Polygons(Mesh *mesh, PolygonContainer &polys)
 {
 	FaceContainer::const_iterator fi;
@@ -327,13 +341,13 @@
 	{
 		Polygon3 *poly = new Polygon3((*fi), mesh);
-		polys.push(poly);
-	}
-}
-
-void BspTree::Copy2PolygonSoup(const ObjectContainer &objects, PolygonQueue &polys)
+		polys.push_back(poly);
+	}
+}
+
+void BspTree::Copy2PolygonSoup(const ObjectContainer &objects, PolygonContainer &polys, int maxPolys)
 {
 	ObjectContainer::const_iterator it, it_end = objects.end();
 
-	int limit = min((int)objects.size(), 1);
+	int limit = maxPolys != 0 ? min((int)objects.size(), maxPolys) : (int)objects.size();
 
 	//for (it = objects.begin(); it != it_end; ++ it)
@@ -375,8 +389,8 @@
 
 	std::stack<BspTraversalData> tStack;
-	PolygonQueue *polys = new PolygonQueue();
+	PolygonContainer *polys = new PolygonContainer();
 	
 	// copy mesh instance polygons into one big polygon soup
-	Copy2PolygonSoup(objects, *polys);
+	Copy2PolygonSoup(objects, *polys, 100);
 
 	BspTraversalData tData(mRoot, mRoot->GetParent(), polys, 0);
@@ -395,8 +409,7 @@
 {
 	//Debug << "Subdividing node\n";
-
-	PolygonQueue *backPolys = new PolygonQueue();
-	PolygonQueue *frontPolys = new PolygonQueue();
-
+	PolygonContainer *backPolys = new PolygonContainer();
+	PolygonContainer *frontPolys = new PolygonContainer();
+int polySize = tData.mPolygons->size();
 	BspNode *node = SubdivideNode(dynamic_cast<BspLeaf *>(tData.mNode),
 								  tData.mParent,
@@ -404,7 +417,7 @@
 								  tData.mDepth,
 								  viewCell,
-								  backPolys,
-								  frontPolys);
-	
+								  frontPolys,
+								  backPolys);
+Debug << "Level " << tData.mDepth << ", all: " << polySize << ", front: " << frontPolys->size() << ", back: " << backPolys->size() << endl;
 	if (!node->IsLeaf()) // node was subdivided
 	{
@@ -423,26 +436,96 @@
 }
 
-Plane3 BspTree::SelectPlane(PolygonQueue *polyQueue) 
-{
-	// TODO: more sophisticated criteria
-	switch (sSplitPlaneStrategy)
-	{
-	case LEAST_SPLITS:
-		break;
-	case NEXT_POLYGON:
-        return polyQueue->front()->GetSupportingPlane();
-		break;
-	default:
-		break;
-	}
+Plane3 BspTree::SelectPlane(PolygonContainer *polygons)  const
+{
+	// most simple strategy: just take next polygon
+	if (sSplitPlaneStrategy == NEXT_POLYGON)
+	{
+		Debug << "simple plane selection\n";
+		return polygons->front()->GetSupportingPlane();
+	}
+	
+	return SelectPlaneHeuristics(polygons, sMaxCandidates);
+}
+
+Plane3 BspTree::SelectPlaneHeuristics(PolygonContainer *polygons, int maxTests) const
+{
+	Debug << "selecting plane heuristics\n";
+
+	int bestValue = 999999;
+
+	Plane3 *bestPlane = NULL;
+	
+	int limit = min((int)polygons->size(), maxTests);
+
+	for (int i = 0; i < limit; ++i)
+	{
+		int candidateIdx = Random((int)polygons->size());
+		Plane3 candidatePlane = (*polygons)[candidateIdx]->GetSupportingPlane();
+		Debug << "choosing new candidate: " << limit << endl;
+		// evaluate current candidate
+		int candidateValue = EvalSplitPlane(polygons, candidatePlane);
+			
+		if (candidateValue < bestValue)
+		{
+			bestPlane = &candidatePlane;
+			bestValue = candidateValue;
+			Debug << "new plane value " << bestValue << endl;
+		}
+	}
+	Debug << "%%%%%%%%%%found value: " << bestValue << endl;
+		
+	return *bestPlane;
+}
+
+int BspTree::EvalSplitPlane(PolygonContainer *polygons, const Plane3 &candidatePlane) const
+{
+	PolygonContainer::const_iterator it;
+
+	int sum = 0, sum2 = 0;
+
+	for (it = polygons->begin(); it < polygons->end(); ++ it)
+	{
+		int classification = (*it)->ClassifyPlane(candidatePlane);
+		
+		if ((sSplitPlaneStrategy == BALANCED_TREE) || (sSplitPlaneStrategy == COMBINED))
+		{
+			sum += EvalForBalancedTree(classification);
+		}
+		
+		if ((sSplitPlaneStrategy == LEAST_SPLITS) || (sSplitPlaneStrategy == COMBINED))
+		{
+			sum2 += EvalForLeastSplits(classification);
+		}
+	}
+
+	// return linear combination of both sums
+	return abs(sum) + abs(sum2);
+}
+
+int BspTree::EvalForBalancedTree(const int classification)
+{
+	if (classification == Polygon3::FRONT_SIDE)
+		return 1;
+	else if (classification == Polygon3::BACK_SIDE)
+		return -1;
+
+	return 0;
+}
+
+int BspTree::EvalForLeastSplits(const int classification)
+{
+	if (classification == Polygon3::SPLIT)
+		return 1;
+
+	return 0;
 }
 
 BspNode *BspTree::SubdivideNode(BspLeaf *leaf, 
 								BspInterior *parent, 
-								PolygonQueue *polys, 
+								PolygonContainer *polys, 
 								const int depth, 
 								ViewCell *viewCell,
-								PolygonQueue *frontPolys, 
-								PolygonQueue *backPolys)
+								PolygonContainer *frontPolys, 
+								PolygonContainer *backPolys)
 {
 	// terminate traversal
@@ -460,5 +543,8 @@
 	// split polygon according to current plane
 	int splits = 0;
+	int polySize = polys->size();
+	
 	node->SplitPolygons(polys, frontPolys, backPolys, splits);
+	Debug << "$$ " << polySize << " " << frontPolys->size() << " " << backPolys->size() << endl; 
  	mStat.splits += splits;
 
@@ -485,4 +571,5 @@
 	environment->GetIntValue("BspTree.Termination.maxDepth", sTermMaxDepth);
 	environment->GetIntValue("BspTree.Termination.maxPolygons", sTermMaxPolygons);
+	environment->GetIntValue("BspTree.maxCandidates", sMaxCandidates);
 
 	//-- extract strategy to choose the next split plane
@@ -497,4 +584,6 @@
 	else if (strcmp(splitPlaneStrategyStr, "leastSplits") == 0)
 		sSplitPlaneStrategy = BspTree::LEAST_SPLITS;
+	else if (strcmp(splitPlaneStrategyStr, "balancedTree") == 0)
+		sSplitPlaneStrategy = BspTree::BALANCED_TREE;
 	else 
 	{
@@ -508,4 +597,6 @@
   // the node became a leaf -> evaluate stats for leafs
   BspLeaf *leaf = dynamic_cast<BspLeaf *>(data.mNode);
+
+  Debug << "evaluating leaf stats\n";
 
   if (data.mDepth >= mTermMaxDepth)
Index: /trunk/VUT/GtpVisibilityPreprocessor/src/Preprocessor.cpp
===================================================================
--- /trunk/VUT/GtpVisibilityPreprocessor/src/Preprocessor.cpp	(revision 237)
+++ /trunk/VUT/GtpVisibilityPreprocessor/src/Preprocessor.cpp	(revision 238)
@@ -68,5 +68,7 @@
 
 	char constructionMethodStr[64];
+	int maxViewCells = 0;
 
+	environment->GetIntValue("BspTree.maxViewCells", maxViewCells);
 	environment->GetStringValue("BspTree.constructionMethod", constructionMethodStr);
 
@@ -90,5 +92,5 @@
 		
 		// derive viewcells from the scene objects
-		ViewCell::DeriveViewCells(objects, mViewcells, 1000);
+		ViewCell::DeriveViewCells(objects, mViewcells, maxViewCells);
 		
 		mBspTree->Construct(mViewcells);
Index: /trunk/VUT/GtpVisibilityPreprocessor/src/Plane3.h
===================================================================
--- /trunk/VUT/GtpVisibilityPreprocessor/src/Plane3.h	(revision 237)
+++ /trunk/VUT/GtpVisibilityPreprocessor/src/Plane3.h	(revision 238)
@@ -44,22 +44,21 @@
   {
 	  const Vector3 v = b - a; // line from A to B
-
 	  float dv = DotProd(mNormal, v);
   	  float u = 0;
 	
-	  if (dv)
+	  if (signum(dv) != 0)
 	  {
 		  u = - Distance(a) / dv;
-		  Debug << "t: " << u << ", dv: " << dv << endl;
+		  Debug << "t: " << u << ", b - a: " << v << ", norm: " << mNormal << ", dist(a): " << - Distance(a) << ", dv: " << dv << endl;
 		  if (coplanar) (*coplanar) = false;
 	  }
 	  else {
-		  Debug << "OHOH: " << u << endl;
 		  if (coplanar) (*coplanar) = true;	  
 	  }
 	  if (t) (*t) = u;
-	  Debug << "A: " << a << ", B: " << b << ", result: " << (a + (u * v)) << endl;
+	  Debug << "result of intersection with A: " << a << ", B: " << b << ":\n" << (a + u * b - u * a) << "\n" << (a + u*v) << "\n\n";
 	  
-	  return a + (u * v);
+	  return a + u * b - u * a; // NOTE: gives better precision than calclulating a + u * v
+	  //return a + (u * v);
   }
 
Index: /trunk/VUT/GtpVisibilityPreprocessor/src/Polygon3.cpp
===================================================================
--- /trunk/VUT/GtpVisibilityPreprocessor/src/Polygon3.cpp	(revision 237)
+++ /trunk/VUT/GtpVisibilityPreprocessor/src/Polygon3.cpp	(revision 238)
@@ -1,4 +1,6 @@
 #include "Polygon3.h"
 #include "Mesh.h"
+
+#define SIDE_TOLERANCE 0.002
 
 Polygon3::Polygon3()
@@ -21,16 +23,20 @@
 }
 
-Plane3 Polygon3::GetSupportingPlane()
+Plane3 Polygon3::GetSupportingPlane() const
 {
+	Debug << "creating plane using vertices: " << mVertices[0] << mVertices[1] << mVertices[2] << endl;
+	Vector3 v1 = mVertices[0] - mVertices[1];
+		Vector3 v2 = mVertices[2] - mVertices[1];
+	Debug << "plane has vectors " <<  v1 << v2  << endl;
 	return Plane3(mVertices[0], mVertices[1], mVertices[2]);
 }
 
-void Polygon3::DeletePolygons(PolygonQueue *polys)
+void Polygon3::DeletePolygons(PolygonContainer *polys)
 {
-	// don't need to store polygon information = delete polygons
+	// don't need to store polygon information => delete polygons
 	while(!polys->empty())
 	{
-		Polygon3 *poly = polys->front();
-		polys->pop();
+		Polygon3 *poly = polys->back();
+		polys->pop_back();
 		DEL_PTR(poly);
 	}
@@ -42,7 +48,9 @@
 	Vector3 ptA = mVertices[mVertices.size() - 1];
 	
-	int sideA = partition->Side(ptA);
+	int sideA = partition->Side(ptA, SIDE_TOLERANCE);
 	
 	VertexContainer::const_iterator it;
+
+	Debug << "\n\nvertex A: " << ptA << ", side A: " << sideA << " (" << partition->Distance(ptA) << ")";
 
 	// find line - plane intersections
@@ -50,5 +58,6 @@
 	{
 		Vector3 ptB = (*it);
-		int sideB = partition->Side(ptB);
+		int sideB = partition->Side(ptB, SIDE_TOLERANCE);
+		Debug << " <=> vertex B: " << ptB << ", side B: " << sideB << " (" << partition->Distance(ptB) << ")\n\n";
 
 		// vertices on different sides => split
@@ -62,9 +71,9 @@
 				// add vertex to both polygons
 				front->mVertices.push_back(splitPt);
-				back->mVertices.push_back(splitPt);
+				back->mVertices.push_back(splitPt); Debug << "front and back polygon + " << splitPt << endl;
 			
 				++ splits;
 			}
-			front->mVertices.push_back(ptB);
+			front->mVertices.push_back(ptB); Debug << "front polygon + " << ptB << endl;
 		}
 		else if (sideB < 0)
@@ -77,9 +86,9 @@
 				// add vertex to both polygons
 				front->mVertices.push_back(splitPt);
-				back->mVertices.push_back(splitPt);
+				back->mVertices.push_back(splitPt); Debug << "front and back polygon + " << splitPt << endl;
 
 				++ splits;
 			}
-			back->mVertices.push_back(ptB);
+			back->mVertices.push_back(ptB); Debug << "back polygon + " << ptB << endl;
 		}
 		else
@@ -87,13 +96,27 @@
 			// vertex on plane => add vertex to both polygons
 			front->mVertices.push_back(ptB);
-			back->mVertices.push_back(ptB);
+			back->mVertices.push_back(ptB); Debug << "front and back polygon + " << ptB << endl;
 		}
 	
 		ptA = ptB;
 		sideA = sideB;
+		Debug << "vertex A: " << ptA << ", side A: " << sideA << " (" << partition->Distance(ptA) << ")";
 	}
+	Debug << "\n*********************\n";
 }
 
-int Polygon3::Side(Plane3 *plane)
+int Polygon3::Side(const Plane3 &plane) const
+{
+	int classification = ClassifyPlane(plane);
+	
+	if (classification == BACK_SIDE)
+		return -1;
+	else if (classification == FRONT_SIDE)
+		return 1;
+
+	return 0;
+}
+
+int Polygon3::ClassifyPlane(const Plane3 &plane) const
 {
 	VertexContainer::const_iterator it;
@@ -102,8 +125,8 @@
 	bool onBackSide = false;
 
-	// find line - plane intersections
+	// find possible line-plane intersections
 	for (it = mVertices.begin(); it != mVertices.end(); ++ it)
 	{
-		int side = plane->Side(*it);
+		int side = plane.Side(*it, SIDE_TOLERANCE);
 		
 		if (side > 0)
@@ -116,5 +139,5 @@
 		}
 
-		if (onFrontSide && onBackSide) // split
+		if (onFrontSide && onBackSide) // split //TODO: check if through vvertex
 		{
 			return SPLIT;
@@ -131,4 +154,5 @@
 	}
 
+	// plane and polygon are coincident
 	return COINCIDENT;
 }
