static Cell_handle findBestCell(const Vector_3 &direction,
		const Vertex_handle &infinity,
		const Cell_handle &startingCell)
{
	DEBUG_START;
	/* FIXME: Maybe some hint will be useful here */
	ASSERT(startingCell->has_vertex(infinity) && "Wrong input");
	Cell_handle bestCell = startingCell;
	Cell_handle nextCell = bestCell;
	double maxProduct = calculateProduct(direction, bestCell, infinity);
	unsigned numIterations = 0;
	do
	{
		++numIterations;
		bestCell = nextCell;
		ASSERT(bestCell->has_vertex(infinity) && "Wrong iteration");
		int infinityIndex = bestCell->index(infinity);
		for (int i = 0; i < NUM_CELL_VERTICES; ++i)
		{
			if (i == infinityIndex)
				continue;
			Cell_handle neighbor = bestCell->neighbor(i);
			double product = calculateProduct(direction,
					neighbor, infinity);
			if (product > maxProduct)
			{
				nextCell = neighbor;
				maxProduct = product;
			}
		}
	} while (nextCell != bestCell);
	ASSERT(bestCell->has_vertex(infinity) && "Wrong result");
	DEBUG_END;
	return bestCell;
}
Example #2
0
bool
is_p_outside(const Point& q, const Triangulation& triang,
             const Cell_handle& start_cell,
             Cell_handle& c, int& u, int& v)
{
   Triangulation::Locate_type lt;
   u = -1; v = -1;
   c = triang.locate(q, lt, u, v, start_cell);
   if( lt == Triangulation::OUTSIDE_AFFINE_HULL )
   {
     cerr << "Point " << q << " is outside the affine hull." << endl;
     return true;
   }
   else if( lt == Triangulation::OUTSIDE_CONVEX_HULL )
     return true;
   else
   {
     if( lt == Triangulation::CELL )
     {
        if( c->outside )
           return true; 
        else
           return false; 
     }
     else if( lt == Triangulation::FACET )
     {
        Cell_handle _c = c->neighbor(u);
        if( c->outside && _c->outside )
           return true; 
        else
           return false; 
     }
     else if( lt == Triangulation::EDGE )
     {
        if( is_outside_VF(triang, Edge(c, u, v)) )
           return true; 
        else
           return false;
     }
     else
     {
        CGAL_assertion( lt == Triangulation::VERTEX );
        return false; 
     }
   }
}
AlphaSimplex3D::
AlphaSimplex3D(const Delaunay3D::Facet& f, const SimplexSet& simplices, const Delaunay3D& Dt)
{
    Cell_handle c = f.first;
    for (int i = 0; i < 4; ++i)
        if (i != f.second)
            Parent::add(c->vertex(i));

    Cell_handle o = c->neighbor(f.second);
    int oi = o->index(c);

    VertexSet::const_iterator v = static_cast<const Parent*>(this)->vertices().begin();
    const DPoint& p1 = (*v++)->point();
    const DPoint& p2 = (*v++)->point();
    const DPoint& p3 = (*v)->point();

    attached_ = false;
    if (!Dt.is_infinite(c->vertex(f.second)) &&
        CGAL::side_of_bounded_sphere(p1, p2, p3,
                                     c->vertex(f.second)->point()) == CGAL::ON_BOUNDED_SIDE)
        attached_ = true;
    else if (!Dt.is_infinite(o->vertex(oi)) &&
             CGAL::side_of_bounded_sphere(p1, p2, p3,
                                          o->vertex(oi)->point()) == CGAL::ON_BOUNDED_SIDE)
        attached_ = true;
    else
        alpha_ = CGAL::squared_radius(p1, p2, p3);

    if (attached_)
    {
        if (Dt.is_infinite(c))
            alpha_ = simplices.find(AlphaSimplex3D(*o))->alpha();
        else if (Dt.is_infinite(o))
            alpha_ = simplices.find(AlphaSimplex3D(*c))->alpha();
        else
            alpha_ = std::min(simplices.find(AlphaSimplex3D(*c))->alpha(),
                              simplices.find(AlphaSimplex3D(*o))->alpha());
    }
}
// Constructs regular triangulation of weighted points.
// Builds graph of cells with voids. Finds connected components of this graph (voids as clusters of cells).
// For each component calculates total void volume and area.
// Excludes roughs on the surface (components, connected to the infinite cell).
bool regular_triangulation_voids(const Wpi_container& points, Voids_result &res)
{
    typedef typename boost::adjacency_list<boost::vecS, boost::vecS, boost::undirectedS, Cell_handle> CellGraph;
    typedef typename boost::graph_traits<CellGraph>::vertex_descriptor GVertex;
    typedef typename boost::graph_traits<CellGraph>::vertex_iterator GVertex_iterator;

    Rt T;            // regular triangulation
    CellGraph G;     // Voronoi subgraph where cells_sqr_r > 0 and edges_sqr_r > 0 (cells and edges with voids)
    GVertex_iterator vi, vi_end;


    res.out_log << "Number of input points for RT : " <<  points.size() << std::endl;
    T.insert(points.begin(), points.end());    // insert all points in a row (this is faster than one insert() at a time).
    T.infinite_vertex()->info().atom_id = -1;  // set special atom_id for dummy infinite triangulation vertex

    assert(T.dimension() == 3);
    /*res.out_log << "Is valid : " << T.is_valid() << std::endl;*/
    res.out_log << "Number of vertices in RT : " << T.number_of_vertices() << std::endl;
    res.out_log << "Number of cells : " << T.number_of_cells() << std::endl;
    res.out_log << "Number of finite cells : " << T.number_of_finite_cells() << std::endl;
    /*res.out_log << "Inf. vert. atom id : " << T.infinite_vertex()->info().atom_id << std::endl;*/

    // Add finite cells having sqr_r > 0 as graph verticies
    Finite_cells_iterator cit, cit_end = T.finite_cells_end();
    for (cit = T.finite_cells_begin(); cit != cit_end; cit++) {
        if (cit->weighted_circumcenter().weight() > 0)       // cached weighted circumcenter computation
            cit->id() = add_vertex(Cell_handle(cit), G);     // store corresponding graph vertex descriptor in cell's id()
    }

    // store one of infinite cells in graph: it will represent all of them. It should be the last vertex in graph with maximal vertex_descriptor.
    const GVertex inf_graph_v = add_vertex(T.infinite_cell(), G);
    res.out_log << "inf_graph_v descriptor : " << inf_graph_v << std::endl;

    // Add graph edges connecting cells with void
    for (boost::tie(vi, vi_end) = vertices(G); vi != vi_end; ++vi) {
        const GVertex v1 = *vi;           // current graph vertex

        if (v1 != inf_graph_v) { // check edges only from finite cells
            const Cell_handle c1 = G[v1];    // current cell

            for (int i = 0; i < 4; i++) {       // for each of four neighbor cells
                const Cell_handle c2 = c1->neighbor(i);
                bool ends_in_void = false;   // do both corresponding Voronoi verticies lie in void space?
                bool on_same_side = false;   // do both ends lie on the same side of corresponding cell facet?
                const Weighted_point &p1 = c1->vertex((i+1)&3)->point();     // weighted points of common facet between c and c2 cells
                const Weighted_point &p2 = c1->vertex((i+2)&3)->point();
                const Weighted_point &p3 = c1->vertex((i+3)&3)->point();
                const Point &wcc = c1->weighted_circumcenter().point();
                GVertex v2;  // neighbor vertex in graph to construct edge to

                if (c2->id() != -1) {    // neighbor cell is finite and in graph: id()=vertex_descriptor
                    v2 = c2->id();
                    ends_in_void = true;
                    on_same_side = (orientation(p1.point(), p2.point(), p3.point(), wcc) ==
                                    orientation(p1.point(), p2.point(), p3.point(), c2->weighted_circumcenter().point()));
                } else if (T.is_infinite(c2))   {
                    v2 = inf_graph_v;    // use our infinite graph vertex as destination if neighbor cell is infinite
                    ends_in_void = true;
                    on_same_side = (orientation(p1.point(), p2.point(), p3.point(), wcc) !=
                                    orientation(p1.point(), p2.point(), p3.point(), c1->vertex(i)->point().point()));  // same side with infinite vertex = different sides with cell vertex
                }

                typename K::Compute_squared_radius_smallest_orthogonal_sphere_3 r_mouth;  // facet bottleneck squared radius (facet closed if < 0)
                if (ends_in_void && (v2 > v1) && (on_same_side || r_mouth(p1, p2, p3) > 0))
                    add_edge(v1, v2, G);  // use ordering v2>v1 to rule out most of the parallel edges: rely on v_inf>v1 for all finite vertices
            }
        }
    }

    res.out_log << "Number of vertices in G : " << num_vertices(G) << std::endl;
    res.out_log << "Number of edges in G : " << num_edges(G) << std::endl;

    // Find connected components on this Voronoi subnetwork
    std::vector<int> component(num_vertices(G));
    int num_components = boost::connected_components(G, &component[0]);
    const int inf_comp_id = component[inf_graph_v];  // component of infinite vertex
    res.out_log << "Number of connected components : " << num_components << std::endl;
    res.out_log << "Component id of infinite vertex : " << inf_comp_id << std::endl;

    // Reserve storage for results
    res.voids.resize(num_components);
    std::fill(res.atom_surf.begin(), res.atom_surf.end(), 0.0L);

    // Calculate total volume of each finite component
    for (boost::tie(vi, vi_end) = vertices(G); vi != vi_end; ++vi) {
        const int comp_id = component[*vi];
        if (comp_id != inf_comp_id) {   // skip infinite component
            Cell_handle cell = G[*vi];  // current cell
            double Vc, Sc;              // cell volume and surface
            Array_double_4 Sa;          // per atom surface in cell
            Vc = cell_void_volume(cell, Sc, Sa);     // void volume of cell and its surface area

            res.voids[comp_id].volume += Vc;  // add to volume of component
            res.voids[comp_id].surface += Sc;
            for (int k = 0; k < 4; k++) {  // process four cell atoms
                int atom_id = cell->vertex(k)->info().atom_id;
                res.atom_surf[atom_id] += Sa[k];     // atom exposed surface
                res.voids[comp_id].atoms.insert(atom_id);  // add to set of cavity atoms
            }
        }
    }

    // Remove skipped infinite component with zero values
    res.voids.erase(res.voids.begin() + inf_comp_id);

    // Sort cavities by volume
    std::sort(res.voids.begin(), res.voids.end(), void_greater);

    return true;
}
Example #5
0
bool is_degenerate_VF(const Triangulation& triang, const Cell_handle& c, const int& fid, const int& uid, const int& vid, const Point& d, const char* prefix)
{
	char degen_op_filename[200];
	strcat(strcpy(degen_op_filename, prefix), ".degen_VF");
	// an extra check - probably not needed.
	if (triang.is_infinite(c) || triang.is_infinite(c->neighbor(fid)) || triang.is_infinite(c->neighbor(6 - fid - uid - vid)))
	{
		return true;
	}
	vector<Cell_handle> VF;
	Facet_circulator fcirc = triang.incident_facets(Edge(c,uid,vid));
	Facet_circulator begin = fcirc;
	do
	{
		if (triang.is_infinite((*fcirc).first))
		{
			cerr << "< Inf VF >";
			return true; // by check-1 it is degenerate.
		}
		Cell_handle cur_c = (*fcirc).first;
		int cur_fid = (*fcirc).second;
		// check if cur_c and its cur_fid neighbors are cospherical.
		if (is_cospherical_pair(triang, Facet(cur_c,cur_fid)))
		{
			cerr << "< Cosph VF >";
			return true; // by check-2 it is degenerate.
		}
		fcirc ++;
	}
	while (fcirc != begin);
	// check-3
	Point vv[3];
	vv[0] = c->voronoi();
	vv[1] = c->neighbor(fid)->voronoi();
	vv[2] = c->neighbor(6 - fid - uid - vid)->voronoi();
	Vector v[3];
	v[0] = vv[0] - d;
	v[1] = vv[1] - d;
	v[2] = vv[2] - d;
	Vector v1xv0 = CGAL::cross_product(v[1], v[0]);
	Vector v0xv2 = CGAL::cross_product(v[0], v[2]);
	if (CGAL::to_double(v1xv0 * v0xv2) < 0)
	{
		ofstream fout;
		fout.open(degen_op_filename, ofstream::app);
		fout << "# prob : v1xv0 * v0xv2 = " <<
			 CGAL::to_double(v1xv0 * v0xv2) << endl;
		fout << "{LIST " << endl;
		fout << "# VF - color yellow " << endl;
		draw_VF(triang, Edge(c, uid, vid), 1, 1, 0, 1, fout);
		fout << "# v0 : segment(driver, voronoi(c)) - color red " << endl;
		draw_segment(Segment(d, vv[0]), 1, 0, 0, 1, fout);
		fout << "# v1 : segment(driver, voronoi(c->neighbor1)) - color green " << endl;
		draw_segment(Segment(d, vv[1]), 0, 1, 0, 1, fout);
		fout << "# v2 : segment(driver, voronoi(c->neighbor2)) - color blue " << endl;
		draw_segment(Segment(d, vv[2]), 0, 0, 1, 1, fout);
		fout << "}" << endl;
		fout.close();
		cerr << "< - v1xv0 * v0xv2 < 0 - >";
		return true;
	}
	return false;
}
Example #6
0
float
sdf( const Point& q, const Mesh &mesh, const vector<double>& weights,
     KdTree& kd_tree, const Triangulation& triang )
{
  VECTOR3 query (CGAL::to_double(q.x()),
                 CGAL::to_double(q.y()),
                 CGAL::to_double(q.z()));
  kd_tree.queryPosition(query);
  // Initialize the search structure, and search all N points
  int n_vid = kd_tree.getNeighbourPositionIndex(0);
  if(n_vid == -1) throw std::runtime_error("No nearest neighbor. MDS empty?");
  CGAL_assertion( ! mesh.vert_list[n_vid].iso());
  MVertex nv = mesh.vert_list[n_vid];
  double min_sq_d = HUGE;
  int n_fid = -1;
  for(int i = 0; i < nv.num_inc_face; i ++)
  {
     MFace f = mesh.face_list[nv.inc_face(i)];
     Point p[3] = {mesh.vert_list[f.get_corner(0)].point(),
                   mesh.vert_list[f.get_corner(1)].point(),
                   mesh.vert_list[f.get_corner(2)].point()};
     Triangle_3 t (p[0], p[1], p[2]);
     Plane_3 H (p[0], p[1], p[2]);
     Point _q = H.projection(q);
     // check if _q is inside t.
     if( t.has_on(_q) )
     {
        double sq_d = CGAL::to_double((q-_q)*(q-_q));
        if( sq_d < min_sq_d ) { min_sq_d = sq_d; n_fid = nv.inc_face(i); }
     }
     else
     {
        for(int j = 0; j < 3; j ++)
        {
           double _d = CGAL::to_double(CGAL::squared_distance(_q,Segment(p[j], p[(j+1)%3])));
           double sq_d = CGAL::to_double((q-_q)*(q-_q)) + _d;
           if( sq_d < min_sq_d ) { min_sq_d = sq_d; n_fid = nv.inc_face(i); }
        }
     }
  }

  // locate the query point in the triang which is already tagged
  // with in-out flag by the reconstruction.
  bool is_q_outside = false;
  Triangulation::Locate_type lt;
  int u = -1, v = -1;
  Cell_handle c = triang.locate(q, lt, u, v);
  if( lt == Triangulation::OUTSIDE_AFFINE_HULL )
  {
     is_q_outside = true;
     cerr << "Point " << q << " is outside the affine hull." << endl;
  }
  else if( lt == Triangulation::OUTSIDE_CONVEX_HULL )
     is_q_outside = true;
  else
  {
     if( lt == Triangulation::CELL )
     {
        if( c->outside )
           is_q_outside = true;
        else
           is_q_outside = false;
     }
     else if( lt == Triangulation::FACET )
     {
        Cell_handle _c = c->neighbor(u);
        if( c->outside && _c->outside )
           is_q_outside = true;
        else
           is_q_outside = false;
     }
     else if( lt == Triangulation::EDGE )
     {
        if( is_outside_VF(triang, Edge(c, u, v)) )
           is_q_outside = true;
        else
           is_q_outside = false;
     }
     else
     {
        CGAL_assertion( lt == Triangulation::VERTEX );
        is_q_outside = false;
     }
  }

  double w;
  if(weights.size() && mesh.face_list[n_fid].label != -1) w = weights[mesh.face_list[n_fid].label];
  else w = 1.0;
  // double w = mesh.face_list[n_fid].w;

  double gen_sdf = 0;
  if( is_q_outside ) gen_sdf = w*sqrt(min_sq_d);
  else gen_sdf = -w*min_sq_d;

#if 0
  double MAX = 10, MIN = -10;

  if( gen_sdf > MAX ) gen_sdf = MAX;
  if( gen_sdf < MIN ) gen_sdf = MIN;
#endif
  return gen_sdf;
}