bool is_polyhedron_geometrically_consistent(Shell* sh)
{
  std::vector<Box> boxes;
  CgalPolyhedron* p = sh->get_cgal_polyhedron();
  boxes.reserve(p->size_of_facets());
  for ( Facet_const_iterator i = p->facets_begin(); i != p->facets_end(); ++i)
  {
    boxes.push_back(
                    Box( i->halfedge()->vertex()->point().bbox()
                        + i->halfedge()->next()->vertex()->point().bbox()
                        + i->halfedge()->next()->next()->vertex()->point().bbox(),
                        i));
  }
  std::vector<const Box*> box_ptr;
  box_ptr.reserve(p->size_of_facets());
  for ( std::vector<Box>::iterator j = boxes.begin(); j != boxes.end(); ++j){
    box_ptr.push_back( &*j);
  }

  CGAL::box_self_intersection_d( box_ptr.begin(), box_ptr.end(), Intersect_facets());
  if (gTriangles.empty())
    return true;
  else 
  {
    std::stringstream st;
    st << "Location: (" 
       << gTriangles[0].vertex(0).x() << ", " 
       << gTriangles[0].vertex(0).y() << ", " 
       << gTriangles[0].vertex(0).z() << ")"; 
    sh->add_error(306, "", st.str());
    gTriangles.clear();
    return false;
  }
}
void intersection( const Polyhedron& P) {
    std::vector<Box> boxes;
    boxes.reserve( P.size_of_facets());
    for ( Facet_const_iterator i = P.facets_begin(); i != P.facets_end(); ++i){
        boxes.push_back(
            Box( i->halfedge()->vertex()->point().bbox()
               + i->halfedge()->next()->vertex()->point().bbox()
               + i->halfedge()->next()->next()->vertex()->point().bbox(),
                 i));
    }
    std::vector<const Box*> box_ptr;
    box_ptr.reserve( P.size_of_facets());
    for ( std::vector<Box>::iterator j = boxes.begin(); j != boxes.end(); ++j){
        box_ptr.push_back( &*j);
    }
    CGAL::box_self_intersection_d( box_ptr.begin(), box_ptr.end(),
                                   Intersect_facets(), std::ptrdiff_t(2000));
}
	Polyhedron_triangulation::Polyhedron_triangulation(const std::vector<Packing_polyhedron>& objects, const Packing_polyhedron& container)
		: nb_groups(0)
	{
		typedef Packing_polyhedron::Point_3 Point_3;
		typedef Packing_polyhedron::Vertex_const_iterator	Vertex_const_iterator;
		typedef Packing_polyhedron::Facet_const_iterator	Facet_const_iterator;

		tetgenio bndmesh;
		bndmesh.firstnumber = 0;
		bndmesh.numberofpoints = 0;
		bndmesh.numberoffacets = 0;
		for (size_t i = 0; i < objects.size(); i++)
		{
			bndmesh.numberofpoints += objects[i].size_of_vertices();
			bndmesh.numberoffacets += objects[i].size_of_facets();
		}
		bndmesh.numberofpoints += container.size_of_vertices();
		bndmesh.numberoffacets += container.size_of_facets();
		bndmesh.pointlist = new REAL[bndmesh.numberofpoints * 3];
		bndmesh.pointmarkerlist = new int[bndmesh.numberofpoints];
		int *marker_ptr = bndmesh.pointmarkerlist;
		REAL *pnt_ptr = bndmesh.pointlist;
		// construct point list
		for (size_t i = 0; i < objects.size(); i++)
		{
			for (Vertex_const_iterator vit = objects[i].vertices_begin(); vit != objects[i].vertices_end(); ++vit)
			{
				Point_3 v = vit->point();
				*pnt_ptr++ = v.x();
				*pnt_ptr++ = v.y();
				*pnt_ptr++ = v.z();
				*marker_ptr++ = i;
			}
			nb_groups++;
		}
		for (Vertex_const_iterator vit = container.vertices_begin(); vit != container.vertices_end(); ++vit)
		{
			Point_3 v = vit->point();
			*pnt_ptr++ = v.x();
			*pnt_ptr++ = v.y();
			*pnt_ptr++ = v.z();
			*marker_ptr++ = -1;
		}
		// construct facets
		bndmesh.facetlist = new tetgenio::facet[bndmesh.numberoffacets];
		//bndmesh.facetmarkerlist = new int[bndmesh.numberoffacets];
		bndmesh.facetmarkerlist = NULL;
		tetgenio::facet *fct_ptr = bndmesh.facetlist;
		for (size_t i = 0; i < objects.size(); i++)
		{
			for (Facet_const_iterator fit = objects[i].facets_begin(); fit != objects[i].facets_end(); ++fit)
			{
				fct_ptr->numberofpolygons = 1;
				fct_ptr->polygonlist = new tetgenio::polygon[fct_ptr->numberofpolygons];
				fct_ptr->numberofholes = 0;
				fct_ptr->holelist = NULL;
				tetgenio::polygon *p = fct_ptr->polygonlist;
				p->numberofvertices = 3; // assume triangle polyhedra
				p->vertexlist = new int[3];
				Packing_polyhedron::Halfedge_const_handle hh = fit->halfedge();
				p->vertexlist[0] = hh->vertex()->idx;
				hh = hh->next();
				p->vertexlist[1] = hh->vertex()->idx;
				hh = hh->next();
				p->vertexlist[2] = hh->vertex()->idx;
				++fct_ptr;
			}
		}
		for (Facet_const_iterator fit = container.facets_begin(); fit != container.facets_end(); ++fit)
		{
			fct_ptr->numberofpolygons = 1;
			fct_ptr->polygonlist = new tetgenio::polygon[fct_ptr->numberofpolygons];
			fct_ptr->numberofholes = 0;
			fct_ptr->holelist = NULL;
			tetgenio::polygon *p = fct_ptr->polygonlist;
			std::list<Packing_polyhedron::Vertex_const_handle> verts;
			p->numberofvertices = 0; // assume triangle polyhedra
			Packing_polyhedron::Halfedge_const_handle hh = fit->halfedge(), hs;
			hs = hh;
			do
			{
				p->numberofvertices++;
				verts.push_back(hh->vertex());
				hh = hh->next();
			} while (hh != hs);
			p->vertexlist = new int[p->numberofvertices];
			int *vl_ptr = p->vertexlist;
			for (std::list<Packing_polyhedron::Vertex_const_handle>::const_iterator it = verts.begin(); it != verts.end(); ++it)
				*vl_ptr++ = (*it)->idx;
			++fct_ptr;
		}
		//std::fill(bndmesh.facetmarkerlist, bndmesh.facetmarkerlist + bndmesh.numberoffacets, 0);
		tetrahedralize("pnY", &bndmesh, &tetra_mesh);
		//std::cout<<"Number of tetrahedra in tetrahedron mesh: " <<tetra_mesh.numberoftetrahedra<<std::endl;
		// debug
		//for (int i = 0; i < bndmesh.numberofpoints; i++)
		//	assert(bndmesh.pointmarkerlist[i] == tetra_mesh.pointmarkerlist[i]);
		//vtx_groups.resize(nb_group);
		//for (int i = 0; i < tetra_mesh.numberofpoints; i++)
		//	vtx_groups[tetra
		cat_cells.resize(nb_groups);
		extract_CAT();
	}