examples/ar-vineyard/ar-simplex3d.hpp
author Dmitriy Morozov <dmitriy@mrzv.org>
Mon, 06 Mar 2023 12:48:28 -0800
changeset 301 41d5aeb87565
parent 86 73a54447b54a
permissions -rw-r--r--
Change all http to https in doc/get-build-install.rst

#include <utilities/log.h>

#if LOGGING
static rlog::RLogChannel* rlARSimplex3D =                       DEF_CHANNEL("ar/simplex3d", rlog::Log_Debug);
#endif

ARSimplex3D::	    
ARSimplex3D(const ARSimplex3D& s): Parent(s)
{ 
	attached_ = s.attached_; 
	alpha_ = s.alpha_; 
	rho_ = s.rho_;
	s_ = s.s_;
	v_ = s.v_;
	phi_const_ = s.phi_const_;
}

ARSimplex3D::
ARSimplex3D(const Parent::Vertex& v)
{
	Parent::add(v);
}

ARSimplex3D::	    
ARSimplex3D(const ::Vertex& v, const Point& z): alpha_(0), rho_(0), v_(0), attached_(false)
{
	for (int i = 0; i < 4; ++i)
		if (v.cell()->vertex(i)->point() == v.point())
			Parent::add(v.cell()->vertex(i));
	s_ = CGAL::squared_distance((*Parent::vertices().begin())->point(), z);

	// phi_const_ will be set by an edge
}

ARSimplex3D::	    
ARSimplex3D(const Edge& e)
{
    Cell_handle c = e.first;
	Parent::add(c->vertex(e.second));
	Parent::add(c->vertex(e.third));
}

ARSimplex3D::	    
ARSimplex3D(const Edge& e, const Point& z, SimplexPhiMap& simplices, const Delaunay& Dt, Facet_circulator facet_bg)
{
    Cell_handle c = e.first;
	Parent::add(c->vertex(e.second));
	Parent::add(c->vertex(e.third));

	Facet_circulator cur = facet_bg;
	while (Dt.is_infinite(*cur))    ++cur; 
	SimplexPhiMap::const_iterator cur_iter = simplices.find(ARSimplex3D(*cur));
	RealValue min = cur_iter->first.alpha();
	RealValue phi_const_min = cur_iter->first.phi_const();
	
	VertexSet::const_iterator v2 = Parent::vertices().begin();
	VertexSet::const_iterator v1 = v2++;
	const Point& p1 = (*v1)->point();
	const Point& p2 = (*v2)->point();
	attached_ = false;
	rho_ = CGAL::squared_radius(p1, p2);

	if (facet_bg != 0) do
	{
		int i0 = (*cur).first->index(*v1);
		int i1 = (*cur).first->index(*v2);
		int i = 6 - i0 - i1 - (*cur).second;

		if (Dt.is_infinite(cur->first->vertex(i)))
		{
			++cur; continue;
			// FIXME: what do we do with infinite cofaces (i.e., what
			// phi_const does a simplex get if its dual Voronoi cell is
			// infinite?
		}
		
		Point p3 = (*cur).first->vertex(i)->point();
		if (CGAL::side_of_bounded_sphere(p1, p2, p3) == CGAL::ON_BOUNDED_SIDE)
			attached_ = true;
		
	    SimplexPhiMap::const_iterator cur_iter = simplices.find(ARSimplex3D(*cur));
		RealValue 								val 				= cur_iter->first.alpha();
		if (val < min) 							min 				= val;
		RealValue 								phi_const_val 		= cur_iter->first.phi_const();
		if (phi_const_val < phi_const_min) 		phi_const_min 		= phi_const_val;
				
		++cur;
	} while (cur != facet_bg);

	if (attached_)
		alpha_ = min;
	else
		alpha_ = rho_;
	phi_const_ = phi_const_min;
	
	// update phi_const_ for v1 and v2 if necessary
	SimplexPhiMap::iterator v1_iter = simplices.find(ARSimplex3D(*v1));
	SimplexPhiMap::iterator v2_iter = simplices.find(ARSimplex3D(*v2));
	if (phi_const_ < v1_iter->second) v1_iter->second = phi_const_;
	if (phi_const_ < v2_iter->second) v2_iter->second = phi_const_;

	
	s_ = CGAL::squared_distance(z, K::Segment_3(p1,p2).supporting_line());
	Point origin(0,0,0);
	Point cc = origin + ((p1 - origin) + (p2 - origin))/2;		// CGAL is funny
	v_ = CGAL::squared_distance(z, cc) - s_;
}

ARSimplex3D::	    
ARSimplex3D(const Facet& f)
{
    Cell_handle c = f.first;
	for (int i = 0; i < 4; ++i)
		if (i != f.second)
			Parent::add(c->vertex(i));
}

ARSimplex3D::	    
ARSimplex3D(const Facet& f, const Point& z, const SimplexPhiMap& simplices, const Delaunay& 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 v3 = Parent::vertices().begin();
	VertexSet::const_iterator v1 = v3++;
	VertexSet::const_iterator v2 = v3++;
	const Point& p1 = (*v1)->point();
	const Point& p2 = (*v2)->point();
	const Point& p3 = (*v3)->point();
	rho_ = squared_radius(p1, p2, p3);
	
	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_ = rho_;
	
	if (Dt.is_infinite(c))
	{
	    SimplexPhiMap::const_iterator o_iter = simplices.find(ARSimplex3D(*o,z));
		if (attached_) alpha_ = o_iter->first.alpha();
		phi_const_ = o_iter->first.phi_const();					// FIXME: it's probably the other way around
	}
	else if (Dt.is_infinite(o))
	{
	    SimplexPhiMap::const_iterator c_iter = simplices.find(ARSimplex3D(*c,z));
		if (attached_) alpha_ = c_iter->first.alpha();
		phi_const_ = c_iter->first.phi_const();					// FIXME: it's probably the other way around
	}
	else
	{
	    SimplexPhiMap::const_iterator o_iter = simplices.find(ARSimplex3D(*o,z));
	    SimplexPhiMap::const_iterator c_iter = simplices.find(ARSimplex3D(*c,z));
		if (attached_) alpha_ = std::min(c_iter->first.alpha(), o_iter->first.alpha());
		phi_const_ = std::min(c_iter->first.phi_const(), o_iter->first.phi_const());
	}

	Point cc = CGAL::circumcenter(p1, p2, p3);
	v_ = CGAL::squared_distance(z, K::Plane_3(p1,p2,p3));
	s_ = CGAL::squared_distance(z, cc) - v_;
}

ARSimplex3D::	    
ARSimplex3D(const Cell& c, const Point& z): attached_(false)
{
	for (int i = 0; i < 4; ++i)
		Parent::add(c.vertex(i));
	VertexSet::const_iterator v = Parent::vertices().begin();
	Point p1 = (*v++)->point();
	Point p2 = (*v++)->point();
	Point p3 = (*v++)->point();
	Point p4 = (*v)->point();
	rho_ = alpha_ = CGAL::squared_radius(p1, p2, p3, p4);

	s_ = 0;
	v_ = CGAL::squared_distance(z, CGAL::circumcenter(p1, p2, p3, p4));

	phi_const_ = rho_ - v_;
}

ARSimplex3D::Cycle
ARSimplex3D::boundary() const
{
	Cycle bdry;
	Parent::Cycle pbdry = Parent::boundary();
	for (Parent::Cycle::const_iterator cur = pbdry.begin(); cur != pbdry.end(); ++cur)
		bdry.push_back(*cur);
	return bdry;
}


bool 
ARSimplex3D::AlphaOrder::
operator()(const ARSimplex3D& first, const ARSimplex3D& second) const
{
	if (first.alpha() == second.alpha())
		return (first.dimension() < second.dimension());
	else
		return (first.alpha() < second.alpha()); 
}

std::ostream& 
ARSimplex3D::
operator<<(std::ostream& out) const
{
    out << this << ": ";
	for (VertexSet::const_iterator cur = Parent::vertices().begin(); cur != Parent::vertices().end(); ++cur)
		out << &(**cur) << ", ";
	out << "value = " << value();

	return out;
}


void update_simplex_phi_map(const ARSimplex3D& s, ARSimplex3D::SimplexPhiMap& simplices)
{
	simplices[s] = s.phi_const();
}
		
void fill_alpha_order(const Delaunay& Dt, const Point& z, ARSimplex3DVector& alpha_order)
{
	ARSimplex3D::SimplexPhiMap simplices;
	for(Cell_iterator cur = Dt.finite_cells_begin(); cur != Dt.finite_cells_end(); ++cur)
		update_simplex_phi_map(ARSimplex3D(*cur, z), simplices);
	rLog(rlARSimplex3D, "Cells inserted");
	for(Vertex_iterator cur = Dt.finite_vertices_begin(); cur != Dt.finite_vertices_end(); ++cur)
		simplices[ARSimplex3D(*cur, z)] = 0;			// only one tetrahedron can have non-negative phi_const value 
														// (namely the one containing z); all other simplices will have a 
														// negative phi_const value, so 0 is safe
	rLog(rlARSimplex3D, "Vertices inserted");

	for(Facet_iterator cur = Dt.finite_facets_begin(); cur != Dt.finite_facets_end(); ++cur)
		update_simplex_phi_map(ARSimplex3D(*cur, z, simplices, Dt), simplices);
	rLog(rlARSimplex3D, "Facets inserted");
	for(Edge_iterator cur = Dt.finite_edges_begin(); cur != Dt.finite_edges_end(); ++cur)
		update_simplex_phi_map(ARSimplex3D(*cur, z, simplices, Dt, Dt.incident_facets(*cur)), simplices);
	rLog(rlARSimplex3D, "Edges inserted");
    
	// Sort simplices by their alpha values
	alpha_order.resize(simplices.size()); ARSimplex3DVector::iterator out = alpha_order.begin();
	for (ARSimplex3D::SimplexPhiMap::const_iterator in = simplices.begin(); in != simplices.end(); ++in, ++out)
		*out = in->first;
	std::sort(alpha_order.begin(), alpha_order.end(), ARSimplex3D::AlphaOrder());
	
	// Update phi_const for vertices
	for (ARSimplex3DVector::iterator cur = alpha_order.begin(); cur != alpha_order.end(); ++cur)
		if (cur->dimension() == 0) cur->set_phi_const(simplices[*cur]);
}