Added examples/alphashapes
authorDmitriy Morozov <morozov@cs.duke.edu>
Fri, 22 Dec 2006 12:52:35 -0500
changeset 8 7b688bc77e86
parent 7 b5dfe607ac17
child 9 4ed0ecccba8c
Added examples/alphashapes
examples/SConscript
examples/alphashapes/SConscript
examples/alphashapes/alpharadius.cpp
examples/alphashapes/alphashapes3d.cpp
examples/alphashapes/alphashapes3d.h
examples/alphashapes/alphashapes3d.hpp
--- a/examples/SConscript	Fri Dec 22 10:25:26 2006 -0500
+++ b/examples/SConscript	Fri Dec 22 12:52:35 2006 -0500
@@ -1,6 +1,6 @@
 Import('*')
 
 SConscript				(['triangle/SConscript',
-#						  'alphashapes/SConscript',
+						  'alphashapes/SConscript',
 						  'grid/SConscript'],
 						 exports=['env', 'external_sources'])
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/examples/alphashapes/SConscript	Fri Dec 22 12:52:35 2006 -0500
@@ -0,0 +1,7 @@
+Import('*')
+
+# Sources
+sources = 				['alphashapes3d.cpp', 'alpharadius.cpp']
+
+for s in sources:
+	Default				(env.Program([s] + external_sources))
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/examples/alphashapes/alpharadius.cpp	Fri Dec 22 12:52:35 2006 -0500
@@ -0,0 +1,113 @@
+#include <sys.h>
+#include <debug.h>
+
+#include "alphashapes3d.h"
+#include <filtration.h>
+#include <iostream>
+#include <fstream>
+
+
+struct SimplexWithDistance: public AlphaSimplex3D
+{
+	SimplexWithDistance(const SimplexWithDistance& s): AlphaSimplex3D(s)				{ distance = s.distance; }
+	SimplexWithDistance(const AlphaSimplex3D& s): AlphaSimplex3D(s)						{ }
+	SimplexWithDistance(const AlphaSimplex3D::Parent& s): AlphaSimplex3D(s)				{ }
+	SimplexWithDistance(const AlphaSimplex3D& s, const Point& p): AlphaSimplex3D(s)		{ set_distance(p); }
+
+	void set_distance(const Point& p)
+	{
+		AlphaSimplex3D::VertexContainer::const_iterator cur = vertices().begin();
+		CGAL::Vector_3<K> v = ((*cur)->point() - p);
+		RealValue min_distance = v*v;
+	
+		while (cur != vertices().end())
+		{
+			v = ((*cur)->point() - p);
+			min_distance = std::min(v*v, min_distance);
+			++cur;
+		}
+	
+		distance = min_distance;
+	}
+
+	RealValue distance;
+};
+typedef std::vector<SimplexWithDistance> 		SimplexVector;
+typedef Filtration<SimplexWithDistance> 		RadiusFiltration;
+
+struct RadiusOrder
+{
+	bool operator()(const SimplexWithDistance& first, const SimplexWithDistance& second) const
+	{
+		if (first.distance == second.distance)
+			return (first.dimension() < second.dimension());
+		else
+			return (first.distance > second.distance); 
+	}
+};
+
+int main(int argc, char** argv) 
+{
+#ifdef CWDEBUG
+	Debug(dc::filtration.on());
+	//Debug(dc::cycle.on());
+
+	dionysus::debug::init();
+#endif
+
+	std::istream& in = std::cin;
+	std::ofstream point_vineyard("point_vineyard.vrt");
+
+	double x,y,z;
+	Delaunay Dt;
+	while(in)
+	{
+		in >> x >> y >> z;
+		Point p(x,y,z);
+		Dt.insert(p);
+	}
+	std::cout << "Delaunay triangulation computed" << std::endl;
+ 
+	AlphaSimplex3DVector alpha_ordering;
+	fill_alpha_order(Dt, alpha_ordering);
+    
+	// Compute r-filtration for each distinct alpha
+	Point p(0,0,0);
+	RadiusOrder ro;
+	SimplexVector radius_ordering;
+	for (AlphaSimplex3DVector::const_iterator cur = alpha_ordering.begin(); cur != alpha_ordering.end(); ++cur)
+	{
+		radius_ordering.push_back(*cur);
+		radius_ordering.back().set_distance(p);
+		if (boost::next(cur)->alpha() == cur->alpha())
+			continue;
+		
+		double current_alpha = CGAL::to_double(cur->value());
+		std::cout << "Current alpha: " << current_alpha << std::endl;
+		std::sort(radius_ordering.begin(), radius_ordering.end(), ro);
+		std::cout << "Radius ordering size: " << radius_ordering.size() << std::endl;
+
+		RadiusFiltration rf;
+		for (SimplexVector::const_iterator cur = radius_ordering.begin(); cur != radius_ordering.end(); ++cur)
+			rf.append(*cur);
+		rf.fill_simplex_index_map();
+		std::cout << "Simplex index map filled" << std::endl;
+		rf.pair_simplices(rf.begin(), rf.end());
+		std::cout << "Pairing computed" << std::endl;
+	
+		for (RadiusFiltration::const_Index cur = rf.begin(); cur != rf.end(); ++cur)
+		{
+			if (!cur->sign()) continue;
+	
+			RealValue d1 = cur->distance;
+			//if (cur == cur->pair())
+			//	std::cout << "Unpaired " << cur->dimension() << ' ' << CGAL::to_double(d1) << std::endl;
+			
+			RealValue d2 = cur->pair()->distance;
+			if (d1 == d2)	continue;
+			point_vineyard << CGAL::to_double(d1) << ' ' << CGAL::to_double(d2) << ' ' << current_alpha << std::endl;
+		}
+	}
+
+	point_vineyard.close();
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/examples/alphashapes/alphashapes3d.cpp	Fri Dec 22 12:52:35 2006 -0500
@@ -0,0 +1,39 @@
+#include <sys.h>
+#include <debug.h>
+
+#include "alphashapes3d.h"
+#include <filtration.h>
+#include <iostream>
+#include <fstream>
+
+
+typedef std::vector<AlphaSimplex3D> 			SimplexVector;
+typedef Filtration<AlphaSimplex3D>				AlphaFiltration;
+
+int main(int argc, char** argv) 
+{
+	// Read in the point set and compute its Delaunay triangulation
+	std::istream& in = std::cin;
+	double x,y,z;
+	Delaunay Dt;
+	while(in)
+	{
+		in >> x >> y >> z;
+		Point p(x,y,z);
+		Dt.insert(p);
+	}
+	std::cout << "Delaunay triangulation computed" << std::endl;
+   
+	AlphaSimplex3DVector alpha_ordering;
+	fill_alpha_order(Dt, alpha_ordering);
+	std::cout << "Simplices: " << alpha_ordering.size() << std::endl;
+
+	// Create the alpha-shape filtration
+	AlphaFiltration af;
+	for (SimplexVector::const_iterator cur = alpha_ordering.begin(); cur != alpha_ordering.end(); ++cur)
+		af.append(*cur);
+	af.fill_simplex_index_map();
+	af.pair_simplices(af.begin(), af.end());
+	std::cout << "Simplices paired" << std::endl;
+}
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/examples/alphashapes/alphashapes3d.h	Fri Dec 22 12:52:35 2006 -0500
@@ -0,0 +1,84 @@
+/**
+ * Author: Dmitriy Morozov
+ * Department of Computer Science, Duke University, 2006
+ */
+
+#ifndef __ALPHASHAPES3D_H__
+#define __ALPHASHAPES3D_H__
+
+#include <CGAL/Exact_predicates_exact_constructions_kernel.h>
+#include <CGAL/Delaunay_triangulation_3.h>
+
+#include <simplex.h>
+#include <types.h>
+
+#include <vector>
+#include <set>
+#include <iostream>
+
+struct K: CGAL::Exact_predicates_exact_constructions_kernel {};
+
+typedef CGAL::Delaunay_triangulation_3<K>    		Delaunay;
+typedef Delaunay::Point                				Point;
+typedef Delaunay::Vertex            				Vertex;
+typedef Delaunay::Vertex_handle            			Vertex_handle;
+typedef Delaunay::Edge								Edge;
+typedef Delaunay::Facet								Facet;
+typedef Delaunay::Cell								Cell;
+typedef Delaunay::Cell_handle						Cell_handle;
+typedef K::FT										RealValue;
+
+typedef Delaunay::Finite_vertices_iterator    		Vertex_iterator;
+typedef Delaunay::Finite_edges_iterator        		Edge_iterator;
+typedef Delaunay::Finite_facets_iterator        	Facet_iterator;
+typedef Delaunay::Finite_cells_iterator        		Cell_iterator;
+typedef Delaunay::Facet_circulator					Facet_circulator;
+
+
+class AlphaSimplex3D: public SimplexWithVertices<Vertex_handle>
+{
+	public:
+		typedef 	std::set<AlphaSimplex3D>							SimplexSet;
+		typedef		SimplexWithVertices<Vertex_handle>					Parent;
+		typedef		Parent::VertexContainer								VertexSet;
+
+    public:
+									AlphaSimplex3D()					{}
+									AlphaSimplex3D(const Parent& p): 
+											Parent(p) 					{}
+									AlphaSimplex3D(const AlphaSimplex3D& s): 
+											Parent(s) 					{ attached_ = s.attached_; alpha_ = s.alpha_; }
+	    							AlphaSimplex3D(const ::Vertex& v);
+		
+								    AlphaSimplex3D(const Edge& e);
+								    AlphaSimplex3D(const Edge& e, const SimplexSet& simplices, Facet_circulator facet_bg);
+		
+								    AlphaSimplex3D(const Facet& f);
+								    AlphaSimplex3D(const Facet& f, const SimplexSet& simplices);
+	    
+									AlphaSimplex3D(const Cell& c);
+	    
+		virtual RealType			value() const						{ return CGAL::to_double(alpha_); }
+		RealValue					alpha() const						{ return alpha_; }
+		bool						attached() const					{ return attached_; }
+
+		// Ordering
+		struct AlphaOrder
+		{ bool operator()(const AlphaSimplex3D& first, const AlphaSimplex3D& second) const; };
+		
+		std::ostream& 				operator<<(std::ostream& out) const;
+		
+	private:
+		RealValue 					alpha_;
+		bool 						attached_;
+};
+
+typedef 			std::vector<AlphaSimplex3D>								AlphaSimplex3DVector;
+void 				fill_alpha_order(const Delaunay& Dt, 
+									 AlphaSimplex3DVector& alpha_order);
+
+std::ostream& 		operator<<(std::ostream& out, const AlphaSimplex3D& s)	{ return s.operator<<(out); }
+
+#include "alphashapes3d.hpp"
+
+#endif // __ALPHASHAPES3D_H__
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/examples/alphashapes/alphashapes3d.hpp	Fri Dec 22 12:52:35 2006 -0500
@@ -0,0 +1,171 @@
+AlphaSimplex3D::	    
+AlphaSimplex3D(const ::Vertex& v): alpha_(0), attached_(false)
+{
+	for (int i = 0; i < 4; ++i)
+		if (v.cell()->vertex(i)->point() == v.point())
+			Parent::add(v.cell()->vertex(i));
+}
+
+AlphaSimplex3D::	    
+AlphaSimplex3D(const Edge& e)
+{
+    Cell_handle c = e.first;
+	Parent::add(c->vertex(e.second));
+	Parent::add(c->vertex(e.third));
+}
+
+AlphaSimplex3D::	    
+AlphaSimplex3D(const Edge& e, const SimplexSet& simplices, 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;
+	SimplexSet::const_iterator cur_iter = simplices.find(AlphaSimplex3D(*cur));
+	while (cur_iter == simplices.end())
+	{
+		++cur; 
+		cur_iter = simplices.find(AlphaSimplex3D(*cur));
+	}
+	RealValue min = cur_iter->alpha();
+	
+	VertexSet::const_iterator v = Parent::vertices().begin();
+	const Point& p1 = (*v++)->point();
+	const Point& p2 = (*v)->point();
+	attached_ = false;
+
+	if (facet_bg != 0) do
+	{
+		VertexSet::const_iterator v = Parent::vertices().begin();
+		int i0 = (*cur).first->index(*v++);
+		int i1 = (*cur).first->index(*v);
+		int i = 6 - i0 - i1 - (*cur).second;
+		Point p3 = (*cur).first->vertex(i)->point();
+
+		cur_iter = simplices.find(AlphaSimplex3D(*cur));
+		if (cur_iter == simplices.end())			// cur is infinite
+		{
+			++cur; continue;
+		}
+		
+		if (CGAL::side_of_bounded_sphere(p1, p2, p3) == CGAL::ON_BOUNDED_SIDE)
+			attached_ = true;
+		RealValue val = cur_iter->alpha();
+		if (val < min)
+			min = val;
+		++cur;
+	} while (cur != facet_bg);
+
+	if (attached_)
+		alpha_ = min;
+	else
+		alpha_ = CGAL::squared_radius(p1, p2);
+}
+
+AlphaSimplex3D::	    
+AlphaSimplex3D(const Facet& f)
+{
+    Cell_handle c = f.first;
+	for (int i = 0; i < 4; ++i)
+		if (i != f.second)
+			Parent::add(c->vertex(i));
+}
+
+AlphaSimplex3D::	    
+AlphaSimplex3D(const Facet& f, const SimplexSet& simplices)
+{
+    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 = Parent::vertices().begin();
+	const Point& p1 = (*v++)->point();
+	const Point& p2 = (*v++)->point();
+	const Point& p3 = (*v)->point();
+	
+	attached_ = false;
+	if (CGAL::side_of_bounded_sphere(p1, p2, p3,
+									 c->vertex(f.second)->point()) == CGAL::ON_BOUNDED_SIDE)
+		attached_ = true;
+	else if (CGAL::side_of_bounded_sphere(p1, p2, p3,
+										  o->vertex(oi)->point()) == CGAL::ON_BOUNDED_SIDE)
+		attached_ = true;
+	else
+		alpha_ = squared_radius(p1, p2, p3);
+	
+	if (attached_)
+	{
+		SimplexSet::const_iterator c_iter = simplices.find(AlphaSimplex3D(*c));
+		SimplexSet::const_iterator o_iter = simplices.find(AlphaSimplex3D(*o));
+		if (c_iter == simplices.end())			// c is infinite
+			alpha_ = o_iter->alpha();
+		else if (o_iter == simplices.end())		// o is infinite
+			alpha_ = c_iter->alpha();
+		else
+			alpha_ = std::min(c_iter->alpha(), o_iter->alpha());
+	}
+}
+
+AlphaSimplex3D::	    
+AlphaSimplex3D(const Cell& c): 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();
+	alpha_ = CGAL::squared_radius(p1, p2, p3, p4);
+}
+
+bool 
+AlphaSimplex3D::AlphaOrder::
+operator()(const AlphaSimplex3D& first, const AlphaSimplex3D& second) const
+{
+	if (first.alpha() == second.alpha())
+		return (first.dimension() < second.dimension());
+	else
+		return (first.alpha() < second.alpha()); 
+}
+
+std::ostream& 
+AlphaSimplex3D::
+operator<<(std::ostream& out) const
+{
+	for (VertexSet::const_iterator cur = Parent::vertices().begin(); cur != Parent::vertices().end(); ++cur)
+		out << **cur << ", ";
+	out << "value = " << value();
+
+	return out;
+}
+
+
+void fill_alpha_order(const Delaunay& Dt, AlphaSimplex3DVector& alpha_order)
+{
+	// Compute all simplices with their alpha values and attachment information
+	AlphaSimplex3D::SimplexSet simplices;
+	for(Cell_iterator cur = Dt.finite_cells_begin(); cur != Dt.finite_cells_end(); ++cur)
+		simplices.insert(AlphaSimplex3D(*cur));
+	std::cout << "Cells inserted" << std::endl;
+	for(Facet_iterator cur = Dt.finite_facets_begin(); cur != Dt.finite_facets_end(); ++cur)
+		simplices.insert(AlphaSimplex3D(*cur, simplices));
+	std::cout << "Facets inserted" << std::endl;
+	for(Edge_iterator cur = Dt.finite_edges_begin(); cur != Dt.finite_edges_end(); ++cur)
+		simplices.insert(AlphaSimplex3D(*cur, simplices, Dt.incident_facets(*cur)));
+	std::cout << "Edges inserted" << std::endl;
+	for(Vertex_iterator cur = Dt.finite_vertices_begin(); cur != Dt.finite_vertices_end(); ++cur)
+		simplices.insert(AlphaSimplex3D(*cur));
+	std::cout << "Vertices inserted" << std::endl;
+    
+	// Sort simplices by their alpha values
+	alpha_order.resize(simplices.size());
+	std::copy(simplices.begin(), simplices.end(), alpha_order.begin());
+	std::sort(alpha_order.begin(), alpha_order.end(), AlphaSimplex3D::AlphaOrder());
+}
+